package com.example.monitoring.service.impl;

import com.example.monitoring.config.MonitoringProperties;
import com.example.monitoring.model.MonitoringResult;
import com.example.monitoring.model.MonitoringStatus;
import com.example.monitoring.model.ServiceCheckResponse;
import com.example.monitoring.service.MonitoringService;
import com.example.monitoring.service.ConfigurationFileService;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.minio.BucketExistsArgs;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import okhttp3.OkHttpClient;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.ThreadMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.MemoryUsage;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.Instant;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.concurrent.TimeUnit;

/**
 * 监控服务实现类
 * 
 * @author rsz
 * @since 2024-04-13
 */
@Slf4j
@Service
public class MonitoringServiceImpl implements MonitoringService {

    /**
     * 带过期时间的缓存项
     */
    private static class CacheItem {
        private final MonitoringResult result;
        private final long expireTime;
        
        public CacheItem(MonitoringResult result) {
            this.result = result;
            this.expireTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(3); // 3分钟过期
        }
        
        public MonitoringResult getResult() {
            return result;
        }
        
        public boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }
    }

    private final MonitoringProperties properties;
    private final CloseableHttpClient httpClient;
    private final ObjectMapper objectMapper;
    private final ConfigurationFileService configurationFileService;
    
    // 缓存最近的监控结果
    private final Map<String, MonitoringResult> monitoringResults = new ConcurrentHashMap<>();
    // 新增：带过期时间的缓存
    private final Map<String, CacheItem> monitoringCache = new ConcurrentHashMap<>();
    
    @Autowired(required = false)
    private RedisConnectionFactory redisConnectionFactory;
    
    @Autowired(required = false)
    private RestHighLevelClient elasticsearchClient;
    
    public MonitoringServiceImpl(MonitoringProperties properties, CloseableHttpClient httpClient, ObjectMapper objectMapper, ConfigurationFileService configurationFileService) {
        this.properties = properties;
        this.httpClient = httpClient;
        this.objectMapper = objectMapper;
        this.configurationFileService = configurationFileService;
    }

    /**
     * 获取缓存中的监控结果，如果过期则返回null
     */
    private MonitoringResult getCachedResult(String key) {
        CacheItem item = monitoringCache.get(key);
        if (item == null || item.isExpired()) {
            if (item != null && item.isExpired()) {
                log.debug("缓存项已过期，移除: {}", key);
                monitoringCache.remove(key);
            }
            return null;
        }
        return item.getResult();
    }
    
    /**
     * 保存监控结果到缓存
     */
    private void putToCache(String key, MonitoringResult result) {
        monitoringCache.put(key, new CacheItem(result));
        log.debug("监控结果已缓存: {} (3分钟过期)", key);
    }
    
    /**
     * 强制刷新指定类型的监控数据
     */
    public MonitoringResult forceRefreshMonitoring(String monitoringType) {
        if (monitoringType == null || monitoringType.trim().isEmpty()) {
            log.warn("监控类型为空，无法执行强制刷新");
            return null;
        }
        
        // String upperType = monitoringType.toUpperCase();
        // log.info("强制刷新监控数据: {}", upperType);
        
        // 清除指定类型的缓存
        String cacheKey = getCacheKey(monitoringType);
        monitoringCache.remove(cacheKey);
        log.debug("已清除 {} 的缓存数据", cacheKey);
        
        // 执行对应的监控方法获取最新数据
        try {
            switch (monitoringType) {
                case "JVM":
                    return monitorJvm();
                case "Redis":
                    return monitorRedis();
                case "MySQL":
                    return monitorMysql();
                case "Elasticsearch":
                    return monitorElasticsearch();
                case "MinIO":
                    return monitorMinio();
                case "System":
                    return monitorSystem();
                default:
                    log.warn("不支持的监控类型: {}", monitoringType);
                    return null;
            }
        } catch (Exception e) {
            log.error("强制刷新监控数据失败: {}", monitoringType, e);
            return null;
        }
    }
    
    /**
     * 获取缓存键名
     */
    private String getCacheKey(String monitoringType) {
        switch (monitoringType.toUpperCase()) {
            case "SYSTEM":
                return "System";
            default:
                return monitoringType;
        }
    }

    @Override
    public List<Boolean> checkAllTargetServicesHealth() {
        List<Boolean> results = new ArrayList<>();
        
        if (properties.getTargetService() == null || properties.getTargetService().isEmpty()) {
            log.warn("未配置目标服务，无法检查健康状态");
            return results;
        }
        
        for (int i = 0; i < properties.getTargetService().size(); i++) {
            results.add(checkTargetServiceHealth(i));
        }
        
        return results;
    }

    @Override
    public boolean checkTargetServiceHealth(int index) {
        try {
            if (properties.getTargetService() == null || 
                properties.getTargetService().isEmpty() || 
                index < 0 || 
                index >= properties.getTargetService().size()) {
                log.warn("目标服务索引无效: {}", index);
                return false;
            }
            
            MonitoringProperties.TargetService targetService = properties.getTargetService().get(index);
            return checkSingleTargetServiceHealth(targetService);
        } catch (Exception e) {
            log.error("检查目标服务健康状态失败，索引: {}", index, e);
            return false;
        }
    }

    @Override
    public boolean checkTargetServiceHealth() {
        // 向后兼容，检查第一个目标服务
        if (properties.getTargetService() == null || properties.getTargetService().isEmpty()) {
            log.warn("未配置目标服务，无法检查健康状态");
            return false;
        }
        
        return checkTargetServiceHealth(0);
    }

    /**
     * 检查单个目标服务的健康状态
     * 
     * @param targetService 目标服务配置
     * @return 服务健康状态
     */
    private boolean checkSingleTargetServiceHealth(MonitoringProperties.TargetService targetService) {
        try {
            String method = targetService.getMethod();
            if (method == null) {
                log.warn("未指定请求方法，默认使用GET");
                method = "GET";
            }
            
            // 记录开始时间
            long startTime = System.currentTimeMillis();
            boolean result;
            
            if ("POST".equalsIgnoreCase(method)) {
                result = checkWithPostMethod(targetService);
            } else if ("GET".equalsIgnoreCase(method)) {
                result = checkWithGetMethod(targetService);
            } else {
                log.warn("不支持的HTTP方法: {}, 请配置为GET或POST", method);
                return false;
            }
            
            // 计算响应时间
            long responseTime = System.currentTimeMillis() - startTime;
            
            // 记录响应时间到监控结果
            MonitoringResult existingResult = monitoringResults.get(targetService.getName());
            if (existingResult != null) {
                Map<String, Object> metrics = existingResult.getMetrics();
                if (metrics == null) {
                    metrics = new HashMap<>();
                }
                metrics.put("responseTime", String.valueOf(responseTime));
                
                // 使用原有的属性创建新的MonitoringResult对象，但更新metrics
                MonitoringResult updatedResult = MonitoringResult.builder()
                        .name(existingResult.getName())
                        .status(result ? MonitoringStatus.NORMAL : MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details(existingResult.getDetails())
                        .metrics(metrics)
                        .build();
                
                monitoringResults.put(targetService.getName(), updatedResult);
                putToCache(targetService.getName(), updatedResult);
            } else {
                // 如果不存在监控结果，创建一个新的
                Map<String, Object> metrics = new HashMap<>();
                metrics.put("responseTime", String.valueOf(responseTime));
                metrics.put("url", targetService.getUrl());
                
                MonitoringResult newResult = MonitoringResult.builder()
                        .name(targetService.getName())
                        .status(result ? MonitoringStatus.NORMAL : MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details(result ? "服务健康" : "服务异常")
                        .metrics(metrics)
                        .build();
                
                monitoringResults.put(targetService.getName(), newResult);
                putToCache(targetService.getName(), newResult);
            }
            
            return result;
        } catch (Exception e) {
            log.error("检查目标服务健康状态失败: {}", targetService.getUrl(), e);
            
            // 记录错误到监控结果
            Map<String, Object> metrics = new HashMap<>();
            metrics.put("url", targetService.getUrl());
            metrics.put("error", e.getMessage());
            
            MonitoringResult errorResult = MonitoringResult.builder()
                    .name(targetService.getName())
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("检查服务失败: " + e.getMessage())
                    .metrics(metrics)
                    .build();
            
            monitoringResults.put(targetService.getName(), errorResult);
            putToCache(targetService.getName(), errorResult);
            return false;
        }
    }
    
    /**
     * 使用POST方法检查服务健康状态
     */
    private boolean checkWithPostMethod(MonitoringProperties.TargetService targetService) throws IOException {
        HttpPost httpPost = new HttpPost(targetService.getUrl());
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setEntity(new StringEntity("{}"));
        
        log.debug("使用POST方法检查目标服务健康状态: {}", targetService.getUrl());
        
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String responseJson = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                log.debug("目标服务响应: {}", responseJson);
                
                try {
                    // 使用修改后的ServiceCheckResponse类解析响应
                    ServiceCheckResponse checkResponse = objectMapper.readValue(responseJson, ServiceCheckResponse.class);
                    log.debug("解析后的响应对象: respCode={}, code={}", checkResponse.getRespCode(), checkResponse.getCode());
                    
                    // 如果respCode存在，使用它进行比较
                    if (checkResponse.getRespCode() != null) {
                        return checkResponse.getRespCode().equals(targetService.getExpectedRespCode());
                    } 
                    
                    // 如果respCode不存在但code存在，可以尝试使用code
                    if (checkResponse.getCode() != null) {
                        log.debug("respCode为空，使用code={} 与期望值 {} 比较", checkResponse.getCode(), targetService.getExpectedRespCode());
                        return checkResponse.getCode().equals(targetService.getExpectedRespCode());
                    }
                    
                    // 如果都不存在，回退到检查HTTP状态码
                    int statusCode = response.getStatusLine().getStatusCode();
                    log.debug("响应中没有有效的状态码，使用HTTP状态码: {}", statusCode);
                    return statusCode == 200;
                } catch (Exception e) {
                    log.warn("解析服务响应失败: {}", e.getMessage());
                    // 如果解析失败，检查HTTP状态码
                    int statusCode = response.getStatusLine().getStatusCode();
                    log.debug("解析失败，使用HTTP状态码: {}", statusCode);
                    return statusCode == 200;
                }
            }
        }
        return false;
    }
    
    /**
     * 使用GET方法检查服务健康状态
     */
    private boolean checkWithGetMethod(MonitoringProperties.TargetService targetService) throws IOException {
        HttpGet httpGet = new HttpGet(targetService.getUrl());
        
        log.debug("使用GET方法检查目标服务健康状态: {}", targetService.getUrl());
        
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            
            if (entity != null) {
                String responseBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                log.debug("目标服务响应: {}", responseBody);
                
                // 首先尝试将响应解析为JSON
                try {
                    ServiceCheckResponse checkResponse = objectMapper.readValue(responseBody, ServiceCheckResponse.class);
                    log.debug("解析后的响应对象: respCode={}, code={}", checkResponse.getRespCode(), checkResponse.getCode());
                    
                    // 优先使用respCode
                    if (checkResponse.getRespCode() != null) {
                        return checkResponse.getRespCode().equals(targetService.getExpectedRespCode());
                    }
                    
                    // 如果respCode不存在但code存在，可以尝试使用code
                    if (checkResponse.getCode() != null) {
                        log.debug("respCode为空，使用code={} 与期望值 {} 比较", checkResponse.getCode(), targetService.getExpectedRespCode());
                        return checkResponse.getCode().equals(targetService.getExpectedRespCode());
                    }
                } catch (Exception e) {
                    log.debug("响应不是标准JSON格式或解析失败，将使用HTTP状态码判断: {}", e.getMessage());
                }
            }
            
            // 如果无法解析响应或响应中没有相关状态码，则使用HTTP状态码判断
            if (targetService.getExpectedRespCode() == null || targetService.getExpectedRespCode() == 200) {
                log.debug("使用HTTP状态码判断: {}", statusCode);
                return statusCode == 200;
            } else {
                log.debug("预期响应码是 {}，实际HTTP状态码是 {}", targetService.getExpectedRespCode(), statusCode);
                return statusCode == targetService.getExpectedRespCode();
            }
        }
    }

    @Override
    public MonitoringResult monitorJvm() {
        // 先检查缓存
        MonitoringResult cachedResult = getCachedResult("JVM");
        if (cachedResult != null) {
            log.debug("返回JVM监控缓存结果");
            return cachedResult;
        }
        
        log.info("执行JVM监控数据采集...");
        
        try {
            // 确保middleware对象已初始化
            ensureMiddlewareInitialized();
            
            if (!properties.getMiddleware().getJvm().isEnabled()) {
                return buildDisabledResult("JVM");
            }
            
            log.debug("开始监控JVM");
            MonitoringProperties.Middleware.Jvm jvmProps = properties.getMiddleware().getJvm();
            
            // 检查JMX URL是否配置
            if (jvmProps.getUrl() == null || jvmProps.getUrl().trim().isEmpty()) {
                log.error("JMX URL未配置");
                return MonitoringResult.builder()
                        .name("JVM")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("JMX URL未配置，请在配置页面设置JMX连接URL")
                        .build();
            }
            
            log.debug("尝试连接JMX服务: {}", jvmProps.getUrl());
            
            // Windows系统JMX连接优化 - 解决RMI主机地址问题
            configureJmxForWindows(jvmProps.getUrl());
            
            JMXServiceURL url = new JMXServiceURL(jvmProps.getUrl());
            Map<String, Object> env = new HashMap<>();
            
            if (jvmProps.getUsername() != null && !jvmProps.getUsername().isEmpty()) {
                log.debug("使用认证信息连接JMX");
                env.put(JMXConnector.CREDENTIALS, new String[]{jvmProps.getUsername(), jvmProps.getPassword()});
            } else {
                log.debug("使用无认证方式连接JMX");
            }
            
            // 添加Windows特定的RMI配置
            if (isWindowsSystem()) {
                env.put("jmx.remote.x.request.timeout", "30000");
                env.put("jmx.remote.x.notification.timeout", "30000");
                env.put("jmx.remote.protocol.provider.pkgs", "com.sun.jmx.remote.protocol");
                log.debug("已应用Windows系统JMX连接优化配置");
            }
            
            try (JMXConnector jmxConnector = JMXConnectorFactory.connect(url, env)) {
                log.debug("JMX连接成功，获取MBean服务器连接");
                MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
                
                // 创建指标Map
                Map<String, Object> metrics = new HashMap<>();
                
                // 1. 获取堆内存详细信息
                log.debug("获取JVM堆内存信息");
                ObjectName memoryMXBean = new ObjectName("java.lang:type=Memory");
                
                // 获取堆内存信息 (HeapMemoryUsage)
                javax.management.openmbean.CompositeData heapMemoryData = 
                    (javax.management.openmbean.CompositeData) mbsc.getAttribute(memoryMXBean, "HeapMemoryUsage");
                
                Map<String, Object> heapMemory = new HashMap<>();
                try {
                    long init = (Long) heapMemoryData.get("init");
                    long used = (Long) heapMemoryData.get("used");
                    long committed = (Long) heapMemoryData.get("committed");
                    long max = (Long) heapMemoryData.get("max");
                    
                    heapMemory.put("init", formatMemorySize(init));
                    heapMemory.put("used", formatMemorySize(used));
                    heapMemory.put("committed", formatMemorySize(committed));
                    heapMemory.put("max", formatMemorySize(max));
                    
                    // 计算使用率，注意处理max可能为-1的情况
                    if (max > 0) {
                        heapMemory.put("usagePercent", String.format("%.2f%%", (double) used / max * 100));
                    } else {
                        heapMemory.put("usagePercent", String.format("%.2f%%", (double) used / committed * 100));
                        heapMemory.put("note", "Max值未设置，使用率基于已提交内存计算");
                    }
                    
                    log.debug("堆内存信息获取成功: used={}, max={}", used, max);
                } catch (Exception e) {
                    log.warn("解析堆内存信息时出现异常", e);
                    heapMemory.put("error", "解析数据失败: " + e.getMessage());
                }
                
                metrics.put("heapMemory", heapMemory);
                
                // 2. 获取非堆内存信息 (NonHeapMemoryUsage)
                try {
                    javax.management.openmbean.CompositeData nonHeapMemoryData = 
                        (javax.management.openmbean.CompositeData) mbsc.getAttribute(memoryMXBean, "NonHeapMemoryUsage");
                    
                    Map<String, Object> nonHeapMemory = new HashMap<>();
                    
                    if (nonHeapMemoryData != null) {
                        long init = (Long) nonHeapMemoryData.get("init");
                        long used = (Long) nonHeapMemoryData.get("used");
                        long committed = (Long) nonHeapMemoryData.get("committed");
                        long max = (Long) nonHeapMemoryData.get("max");
                        
                        nonHeapMemory.put("init", formatMemorySize(init));
                        nonHeapMemory.put("used", formatMemorySize(used));
                        nonHeapMemory.put("committed", formatMemorySize(committed));
                        nonHeapMemory.put("max", max <= 0 ? "未限制" : formatMemorySize(max));
                        
                        // 非堆内存可能返回-1表示没有限制
                        if (max > 0) {
                            nonHeapMemory.put("usagePercent", String.format("%.2f%%", (double) used / max * 100));
                        } else {
                            nonHeapMemory.put("usagePercent", String.format("%.2f%%", (double) used / committed * 100));
                            nonHeapMemory.put("note", "Max值未设置，使用率基于已提交内存计算");
                        }
                        
                        log.debug("非堆内存信息获取成功: used={}, committed={}, max={}", used, committed, max);
                    } else {
                        nonHeapMemory.put("error", "无法获取非堆内存数据");
                        log.warn("无法获取非堆内存数据，返回值为null");
                    }
                    
                    metrics.put("nonHeapMemory", nonHeapMemory);
                } catch (Exception e) {
                    log.warn("获取非堆内存信息时出现异常", e);
                    Map<String, Object> nonHeapMemory = new HashMap<>();
                    nonHeapMemory.put("error", "获取数据失败: " + e.getMessage());
                    metrics.put("nonHeapMemory", nonHeapMemory);
                }
                
                // 3. 获取线程详细信息
                try {
                    log.debug("获取JVM线程信息");
                    ObjectName threadMXBean = new ObjectName("java.lang:type=Threading");
                    Integer threadCount = (Integer) mbsc.getAttribute(threadMXBean, "ThreadCount");
                    Integer peakThreadCount = (Integer) mbsc.getAttribute(threadMXBean, "PeakThreadCount");
                    Integer daemonThreadCount = (Integer) mbsc.getAttribute(threadMXBean, "DaemonThreadCount");
                    Long totalStartedThreadCount = (Long) mbsc.getAttribute(threadMXBean, "TotalStartedThreadCount");
                    
                    Map<String, Object> threadInfo = new HashMap<>();
                    threadInfo.put("current", threadCount);
                    threadInfo.put("peak", peakThreadCount);
                    threadInfo.put("daemon", daemonThreadCount);
                    threadInfo.put("totalStarted", totalStartedThreadCount);
                    
                    // 计算额外的线程指标
                    threadInfo.put("nonDaemon", threadCount - daemonThreadCount);
                    
                    log.debug("线程信息获取成功: 当前线程数={}, 峰值线程数={}", threadCount, peakThreadCount);
                    metrics.put("threadInfo", threadInfo);
                } catch (Exception e) {
                    log.warn("获取线程信息时出现异常", e);
                    Map<String, Object> threadInfo = new HashMap<>();
                    threadInfo.put("error", "获取数据失败: " + e.getMessage());
                    metrics.put("threadInfo", threadInfo);
                }
                
                // 4. 获取类加载信息
                try {
                    log.debug("获取JVM类加载信息");
                    ObjectName classLoadingMXBean = new ObjectName("java.lang:type=ClassLoading");
                    Integer loadedClassCount = (Integer) mbsc.getAttribute(classLoadingMXBean, "LoadedClassCount");
                    Long totalLoadedClassCount = (Long) mbsc.getAttribute(classLoadingMXBean, "TotalLoadedClassCount");
                    Long unloadedClassCount = (Long) mbsc.getAttribute(classLoadingMXBean, "UnloadedClassCount");
                    
                    Map<String, Object> classInfo = new HashMap<>();
                    classInfo.put("loaded", loadedClassCount);
                    classInfo.put("totalLoaded", totalLoadedClassCount);
                    classInfo.put("unloaded", unloadedClassCount);
                    
                    log.debug("类加载信息获取成功: 已加载类数={}, 总加载类数={}", loadedClassCount, totalLoadedClassCount);
                    metrics.put("classLoading", classInfo);
                } catch (Exception e) {
                    log.warn("获取类加载信息时出现异常", e);
                    Map<String, Object> classInfo = new HashMap<>();
                    classInfo.put("error", "获取数据失败: " + e.getMessage());
                    metrics.put("classLoading", classInfo);
                }
                
                // 5. 获取GC详细信息
                try {
                    log.debug("获取JVM GC信息");
                    ObjectName gcMXBean = new ObjectName("java.lang:type=GarbageCollector,*");
                    Set<ObjectName> gcNames = mbsc.queryNames(gcMXBean, null);
                    
                    if (gcNames == null || gcNames.isEmpty()) {
                        log.warn("未找到GC收集器");
                        Map<String, Object> gcInfo = new HashMap<>();
                        gcInfo.put("error", "未找到GC收集器");
                        metrics.put("gc", gcInfo);
                    } else {
                        Map<String, Object> gcInfo = new HashMap<>();
                        long totalGcCount = 0;
                        long totalGcTime = 0;
                        
                        for (ObjectName gc : gcNames) {
                            try {
                                String gcName = gc.getKeyProperty("name");
                                Long gcCount = (Long) mbsc.getAttribute(gc, "CollectionCount");
                                Long gcTime = (Long) mbsc.getAttribute(gc, "CollectionTime");
                                
                                if (gcName != null && gcCount != null && gcTime != null) {
                                    Map<String, Object> collectorInfo = new HashMap<>();
                                    collectorInfo.put("count", gcCount);
                                    collectorInfo.put("time", gcTime + "ms");
                                    
                                    if (gcCount > 0) {
                                        collectorInfo.put("avgTimePerGC", String.format("%.2fms", (double) gcTime / gcCount));
                                    } else {
                                        collectorInfo.put("avgTimePerGC", "0ms");
                                    }
                                    
                                    // 获取内存池信息
                                    try {
                                        String[] memoryPoolNames = (String[]) mbsc.getAttribute(gc, "MemoryPoolNames");
                                        if (memoryPoolNames != null && memoryPoolNames.length > 0) {
                                            collectorInfo.put("memoryPools", String.join(", ", memoryPoolNames));
                                        }
                                    } catch (Exception e) {
                                        log.debug("获取GC内存池信息失败: {}", e.getMessage());
                                    }
                                    
                                    gcInfo.put(gcName, collectorInfo);
                                    totalGcCount += gcCount;
                                    totalGcTime += gcTime;
                                }
                            } catch (Exception e) {
                                log.warn("处理GC收集器信息时出现异常: {}", e.getMessage());
                            }
                        }
                        
                        // 添加总计信息
                        Map<String, Object> totalGcInfo = new HashMap<>();
                        totalGcInfo.put("count", totalGcCount);
                        totalGcInfo.put("time", totalGcTime + "ms");
                        
                        if (totalGcCount > 0) {
                            totalGcInfo.put("avgTimePerGC", String.format("%.2fms", (double) totalGcTime / totalGcCount));
                        } else {
                            totalGcInfo.put("avgTimePerGC", "0ms");
                        }
                        
                        gcInfo.put("total", totalGcInfo);
                        metrics.put("gc", gcInfo);
                        log.debug("GC信息获取成功: 收集器数量={}, 总收集次数={}", gcNames.size(), totalGcCount);
                    }
                } catch (Exception e) {
                    log.warn("获取GC信息时出现异常", e);
                    Map<String, Object> gcInfo = new HashMap<>();
                    gcInfo.put("error", "获取数据失败: " + e.getMessage());
                    metrics.put("gc", gcInfo);
                }
                
                // 6. 获取操作系统信息和CPU使用情况
                try {
                    log.debug("获取JVM操作系统信息");
                    ObjectName osMXBean = new ObjectName("java.lang:type=OperatingSystem");
                    
                    Map<String, Object> osInfo = new HashMap<>();
                    
                    // 获取基本操作系统信息
                    try {
                        String osName = (String) mbsc.getAttribute(osMXBean, "Name");
                        String osVersion = (String) mbsc.getAttribute(osMXBean, "Version");
                        String osArch = (String) mbsc.getAttribute(osMXBean, "Arch");
                        Integer availableProcessors = (Integer) mbsc.getAttribute(osMXBean, "AvailableProcessors");
                        
                        osInfo.put("name", osName);
                        osInfo.put("version", osVersion);
                        osInfo.put("arch", osArch);
                        osInfo.put("availableProcessors", availableProcessors);
                    } catch (Exception e) {
                        log.warn("获取基本操作系统信息失败: {}", e.getMessage());
                    }
                    
                    // 获取系统负载信息
                    try {
                        Double systemLoadAverage = (Double) mbsc.getAttribute(osMXBean, "SystemLoadAverage");
                        if (systemLoadAverage != null && systemLoadAverage >= 0) {
                            osInfo.put("systemLoadAverage", String.format("%.2f", systemLoadAverage));
                        } else {
                            osInfo.put("systemLoadAverage", "N/A");
                        }
                    } catch (Exception e) {
                        log.warn("获取系统负载信息失败: {}", e.getMessage());
                        osInfo.put("systemLoadAverage", "N/A");
                    }
                    
                    // 获取CPU时间
                    try {
                        Long processCpuTime = (Long) mbsc.getAttribute(osMXBean, "ProcessCpuTime");
                        if (processCpuTime != null) {
                            osInfo.put("processCpuTime", formatCpuTime(processCpuTime));
                        }
                    } catch (Exception e) {
                        log.warn("获取CPU时间信息失败: {}", e.getMessage());
                    }
                    
                    // 获取系统内存信息
                    try {
                        Long totalPhysicalMemorySize = (Long) mbsc.getAttribute(osMXBean, "TotalPhysicalMemorySize");
                        Long freePhysicalMemorySize = (Long) mbsc.getAttribute(osMXBean, "FreePhysicalMemorySize");
                        
                        if (totalPhysicalMemorySize != null) {
                            osInfo.put("totalPhysicalMemory", formatMemorySize(totalPhysicalMemorySize));
                        }
                        
                        if (freePhysicalMemorySize != null) {
                            osInfo.put("freePhysicalMemory", formatMemorySize(freePhysicalMemorySize));
                        }
                        
                        if (totalPhysicalMemorySize != null && freePhysicalMemorySize != null) {
                            double usedPercent = 100.0 * (totalPhysicalMemorySize - freePhysicalMemorySize) / totalPhysicalMemorySize;
                            osInfo.put("physicalMemoryUsage", String.format("%.2f%%", usedPercent));
                        }
                    } catch (Exception e) {
                        log.warn("获取系统内存信息失败: {}", e.getMessage());
                    }
                    
                    // 获取JVM启动时间和运行时长
                    try {
                        Long startTime = (Long) mbsc.getAttribute(new ObjectName("java.lang:type=Runtime"), "StartTime");
                        if (startTime != null) {
                            long uptime = System.currentTimeMillis() - startTime;
                            osInfo.put("jvmStartTime", new java.util.Date(startTime).toString());
                            osInfo.put("jvmUptime", formatUptime(uptime));
                        }
                    } catch (Exception e) {
                        log.warn("获取JVM启动时间信息失败: {}", e.getMessage());
                    }
                    
                    log.debug("操作系统信息获取成功");
                    metrics.put("os", osInfo);
                } catch (Exception e) {
                    log.warn("获取操作系统信息失败", e);
                    Map<String, Object> osInfo = new HashMap<>();
                    osInfo.put("error", "获取数据失败: " + e.getMessage());
                    metrics.put("os", osInfo);
                }
                
                log.debug("收集JVM监控指标完成");
                
                MonitoringResult result = MonitoringResult.builder()
                        .name("JVM")
                        .status(MonitoringStatus.NORMAL)
                        .monitorTime(LocalDateTime.now())
                        .details("JVM监控正常")
                        .metrics(metrics)
                        .build();
                
                monitoringResults.put("JVM", result);
                putToCache("JVM", result);
                return result;
            } catch (java.rmi.ConnectException e) {
                log.error("JMX连接被拒绝，请检查目标JVM是否已开启JMX及端口是否正确: {}", e.getMessage());
                
                // 生成Windows特定的错误详情和解决建议
                String errorDetails = buildJmxConnectionErrorDetails(e, jvmProps.getUrl());
                
                return MonitoringResult.builder()
                        .name("JVM")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details(errorDetails)
                        .build();
            } catch (javax.management.InstanceNotFoundException e) {
                log.error("JMX MBean未找到: {}", e.getMessage());
                return MonitoringResult.builder()
                        .name("JVM")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("JMX MBean未找到: " + e.getMessage())
                        .build();
            } catch (SecurityException e) {
                log.error("JMX安全验证失败: {}", e.getMessage());
                return MonitoringResult.builder()
                        .name("JVM")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("JMX安全验证失败: " + e.getMessage() + "。请检查用户名和密码是否正确。")
                        .build();
            }
        } catch (Exception e) {
            log.error("监控JVM失败", e);
            MonitoringResult result = MonitoringResult.builder()
                    .name("JVM")
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("JVM监控失败: " + e.getMessage())
                    .build();
            
            monitoringResults.put("JVM", result);
            return result;
        }
    }
    
    /**
     * 格式化内存大小，转为可读格式
     */
    private String formatMemorySize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024.0));
        } else {
            return String.format("%.2f GB", bytes / (1024.0 * 1024.0 * 1024.0));
        }
    }
    
    /**
     * 格式化CPU时间，从纳秒转为可读格式
     */
    private String formatCpuTime(long nanos) {
        // 纳秒转为毫秒
        double millis = nanos / 1000000.0;
        if (millis < 1000) {
            return String.format("%.2f ms", millis);
        } 
        // 毫秒转为秒
        double seconds = millis / 1000.0;
        if (seconds < 60) {
            return String.format("%.2f s", seconds);
        }
        // 秒转为分钟
        double minutes = seconds / 60.0;
        if (minutes < 60) {
            return String.format("%.2f min", minutes);
        }
        // 分钟转为小时
        double hours = minutes / 60.0;
        return String.format("%.2f h", hours);
    }

    /**
     * 格式化运行时间，从毫秒转为可读格式
     */
    private String formatUptime(long uptime) {
        long days = uptime / (24 * 60 * 60 * 1000);
        long hours = (uptime % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000);
        long minutes = (uptime % (60 * 60 * 1000)) / (60 * 1000);
        long seconds = (uptime % (60 * 1000)) / 1000;
        
        StringBuilder sb = new StringBuilder();
        if (days > 0) {
            sb.append(days).append("天 ");
        }
        if (hours > 0 || days > 0) {
            sb.append(hours).append("小时 ");
        }
        if (minutes > 0 || hours > 0 || days > 0) {
            sb.append(minutes).append("分钟 ");
        }
        sb.append(seconds).append("秒");
        
        return sb.toString();
    }
    
    /**
     * 配置JMX连接以解决Windows系统下的RMI主机地址问题
     * 
     * @param jmxUrl JMX连接URL
     */
    private void configureJmxForWindows(String jmxUrl) {
        if (!isWindowsSystem()) {
            return;
        }
        
        try {
            // 解析JMX URL获取主机地址
            String hostFromUrl = extractHostFromJmxUrl(jmxUrl);
            if (hostFromUrl != null) {
                // 强制设置RMI服务器主机名，解决Windows下IP地址错误问题
                String originalRmiHostname = System.getProperty("java.rmi.server.hostname");
                System.setProperty("java.rmi.server.hostname", hostFromUrl);
                log.debug("Windows系统JMX优化：设置java.rmi.server.hostname = {}", hostFromUrl);
                
                // 设置额外的网络配置
                System.setProperty("java.net.preferIPv4Stack", "true");
                System.setProperty("java.rmi.server.useCodebaseOnly", "true");
                
                log.debug("已应用Windows系统JMX网络配置优化");
                
                // 如果之前有设置，在日志中记录
                if (originalRmiHostname != null) {
                    log.debug("原java.rmi.server.hostname: {}", originalRmiHostname);
                }
            }
        } catch (Exception e) {
            log.warn("配置Windows JMX优化时出现异常，将使用默认配置: {}", e.getMessage());
        }
    }
    
    /**
     * 从JMX URL中提取主机地址
     * 
     * @param jmxUrl JMX连接URL，格式如：service:jmx:rmi:///jndi/rmi://127.0.0.1:37399/jmxrmi
     * @return 主机地址，如：127.0.0.1
     */
    private String extractHostFromJmxUrl(String jmxUrl) {
        if (jmxUrl == null || jmxUrl.trim().isEmpty()) {
            return null;
        }
        
        try {
            // 匹配 rmi://主机:端口 的模式
            java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("rmi://([^:/]+):\\\\d+");
            java.util.regex.Matcher matcher = pattern.matcher(jmxUrl);
            
            if (matcher.find()) {
                String host = matcher.group(1);
                log.debug("从JMX URL中提取主机地址: {}", host);
                return host;
            }
            
            log.warn("无法从JMX URL中提取主机地址: {}", jmxUrl);
            return null;
        } catch (Exception e) {
            log.warn("解析JMX URL时出现异常: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 检查当前系统是否为Windows系统
     * 
     * @return true如果是Windows系统
     */
    private boolean isWindowsSystem() {
        String osName = System.getProperty("os.name");
        boolean isWindows = osName != null && osName.toLowerCase().contains("windows");
        log.debug("操作系统检测: {} -> {}", osName, isWindows ? "Windows" : "非Windows");
        return isWindows;
    }
    
    /**
     * 构建JMX连接错误的详细信息和解决建议
     * 
     * @param e 连接异常
     * @param jmxUrl 配置的JMX URL
     * @return 详细的错误信息和解决建议
     */
    private String buildJmxConnectionErrorDetails(java.rmi.ConnectException e, String jmxUrl) {
        StringBuilder details = new StringBuilder();
        String errorMessage = e.getMessage();
        
        details.append("JMX连接失败: ").append(errorMessage).append("\n\n");
        
        // 检查是否是Windows系统的特定错误
        if (isWindowsSystem() && errorMessage != null && errorMessage.contains("Connection refused to host")) {
            details.append("【Windows系统特定问题检测】\n");
            
            // 提取错误中的IP地址
            java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("Connection refused to host ([0-9.]+)");
            java.util.regex.Matcher matcher = pattern.matcher(errorMessage);
            
            if (matcher.find()) {
                String failedHost = matcher.group(1);
                String configuredHost = extractHostFromJmxUrl(jmxUrl);
                
                details.append("• 检测到Windows系统RMI网络配置问题\n");
                details.append("• 配置的主机地址: ").append(configuredHost != null ? configuredHost : "无法解析").append("\n");
                details.append("• 实际尝试连接的地址: ").append(failedHost).append("\n\n");
                
                if (!failedHost.equals(configuredHost)) {
                    details.append("【问题分析】\n");
                    details.append("Windows系统下，RMI服务器可能选择了错误的网络接口地址。\n");
                    details.append("本系统已尝试应用Windows优化配置，但仍然失败。\n\n");
                }
            }
            
            details.append("【解决建议】\n");
            details.append("1. 确保目标Java应用已开启JMX远程连接，添加以下JVM参数：\n");
            details.append("   -Dcom.sun.management.jmxremote\n");
            details.append("   -Dcom.sun.management.jmxremote.port=37399\n");
            details.append("   -Dcom.sun.management.jmxremote.authenticate=false\n");
            details.append("   -Dcom.sun.management.jmxremote.ssl=false\n");
            details.append("   -Djava.rmi.server.hostname=127.0.0.1\n\n");
            
            details.append("2. Windows系统特定配置（在目标Java应用中添加）：\n");
            details.append("   -Djava.net.preferIPv4Stack=true\n");
            details.append("   -Djava.rmi.server.useCodebaseOnly=true\n\n");
            
            details.append("3. 检查网络和防火墙：\n");
            details.append("   • 确保端口37399未被防火墙阻止\n");
            details.append("   • 确保没有其他应用占用该端口\n");
            details.append("   • 如果是本地监控，建议使用127.0.0.1而不是具体IP地址\n\n");
            
            details.append("4. 验证目标服务状态：\n");
            details.append("   • 确保目标Java应用正在运行\n");
            details.append("   • 检查应用日志是否有JMX相关错误\n");
            details.append("   • 可以使用jconsole工具测试JMX连接\n");
            
        } else {
            // 非Windows系统或其他类型错误
            details.append("【通用解决建议】\n");
            details.append("1. 确保目标Java应用已开启JMX远程连接\n");
            details.append("2. 检查配置的主机地址和端口是否正确\n");
            details.append("3. 确保网络连通性和防火墙设置\n");
            details.append("4. 验证JMX认证配置（如果启用了认证）\n");
        }
        
        return details.toString();
    }

    @Override
    public MonitoringResult monitorRedis() {
        // 先检查缓存
        MonitoringResult cachedResult = getCachedResult("Redis");
        if (cachedResult != null) {
            log.debug("返回Redis监控缓存结果");
            return cachedResult;
        }
        
        log.info("执行Redis监控数据采集...");
        
        try {
            // 确保middleware对象已初始化
            ensureMiddlewareInitialized();
            
            // 动态从配置文件获取Redis配置
            MonitoringProperties loadedProperties = configurationFileService.loadConfiguration();
            MonitoringProperties.Middleware.Redis redisConfig = null;
            
            // 优先使用配置文件中的配置
            if (loadedProperties != null && loadedProperties.getMiddleware() != null && 
                loadedProperties.getMiddleware().getRedis() != null && 
                loadedProperties.getMiddleware().getRedis().isEnabled()) {
                redisConfig = loadedProperties.getMiddleware().getRedis();
                log.debug("使用配置文件中的Redis配置: host={}, port={}", 
                         redisConfig.getHost(), redisConfig.getPort());
            } 
            // 如果配置文件中没有，则使用静态配置
            else if (properties.getMiddleware().getRedis().isEnabled()) {
                redisConfig = properties.getMiddleware().getRedis();
                log.debug("使用静态配置中的Redis配置: host={}, port={}", 
                         redisConfig.getHost(), redisConfig.getPort());
            }
            
            if (redisConfig == null || !redisConfig.isEnabled()) {
                return buildDisabledResult("Redis");
            }
            
            log.debug("开始监控Redis，动态配置: {}:{}", redisConfig.getHost(), redisConfig.getPort());
            
            // 每次都动态创建Redis连接工厂
            RedisConnectionFactory dynamicConnectionFactory = null;
            RedisConnection connection = null;
            
            try {
                // 创建Redis配置
                org.springframework.data.redis.connection.RedisStandaloneConfiguration config = 
                    new org.springframework.data.redis.connection.RedisStandaloneConfiguration();
                config.setHostName(redisConfig.getHost());
                config.setPort(redisConfig.getPort());

                if (redisConfig.getPassword() != null && !redisConfig.getPassword().isEmpty()) {
                    config.setPassword(redisConfig.getPassword());
                    log.debug("Redis配置包含密码认证");
                }

                // 配置连接池
                redis.clients.jedis.JedisPoolConfig poolConfig = new redis.clients.jedis.JedisPoolConfig();
                poolConfig.setMaxTotal(8);
                poolConfig.setMaxIdle(8);
                poolConfig.setMinIdle(0);
                poolConfig.setTestOnBorrow(true);
                poolConfig.setTestOnReturn(true);
                poolConfig.setTestOnCreate(true);
                poolConfig.setTestWhileIdle(true);

                // 创建连接配置

                org.springframework.data.redis.connection.jedis.JedisClientConfiguration clientConfig = org.springframework.data.redis.connection.jedis.JedisClientConfiguration.builder().usePooling().poolConfig(poolConfig).build();
                // 创建连接工厂
                org.springframework.data.redis.connection.jedis.JedisConnectionFactory factory = 
                    new org.springframework.data.redis.connection.jedis.JedisConnectionFactory(config, clientConfig);
                factory.afterPropertiesSet();
                dynamicConnectionFactory = factory;
                
                // 获取连接
                connection = dynamicConnectionFactory.getConnection();
                log.debug("动态Redis连接创建成功: {}:{}", redisConfig.getHost(), redisConfig.getPort());
                
            } catch (Exception e) {
                log.error("动态创建Redis连接失败: {}:{}", redisConfig.getHost(), redisConfig.getPort(), e);
                MonitoringResult result = MonitoringResult.builder()
                        .name("Redis")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("Redis连接失败 (" + redisConfig.getHost() + ":" + redisConfig.getPort() + "): " + e.getMessage())
                        .build();
                monitoringResults.put("Redis", result);
                return result;
            }
            
            if (connection != null) {
                try {
                    // 获取Redis信息
                    Properties info = connection.info();
                    Properties clientInfo = connection.info("clients");
                    Properties memoryInfo = connection.info("memory");
                    Properties statsInfo = connection.info("stats");
                    Properties persistenceInfo = connection.info("persistence");
                    Properties serverInfo = connection.info("server");
                    Properties cpuInfo = connection.info("cpu");
                    
                    // 获取Redis状态
                    String redisVersion = serverInfo.getProperty("redis_version");
                    String redisMode = serverInfo.getProperty("redis_mode");
                    String osVersion = serverInfo.getProperty("os");
                    String tcpPort = serverInfo.getProperty("tcp_port");
                    String uptime = serverInfo.getProperty("uptime_in_seconds");
                    
                    // 客户端连接
                    String connectedClients = clientInfo.getProperty("connected_clients");
                    String blockedClients = clientInfo.getProperty("blocked_clients");
                    String maxClients = clientInfo.getProperty("maxclients");
                    
                    // 内存使用
                    String usedMemory = memoryInfo.getProperty("used_memory_human");
                    String maxMemory = memoryInfo.getProperty("maxmemory_human");
                    String usedMemoryRss = memoryInfo.getProperty("used_memory_rss_human");
                    String memFragmentationRatio = memoryInfo.getProperty("mem_fragmentation_ratio");
                    
                    // 计算内存使用率
                    String memoryUsagePercent = "N/A";
                    try {
                        long used = Long.parseLong(memoryInfo.getProperty("used_memory"));
                        String maxMemRaw = memoryInfo.getProperty("maxmemory");
                        if (maxMemRaw != null && !maxMemRaw.equals("0")) {
                            long max = Long.parseLong(maxMemRaw);
                            if (max > 0) {
                                double percent = (double) used / max * 100;
                                memoryUsagePercent = String.format("%.2f%%", percent);
                            }
                        }
                    } catch (NumberFormatException e) {
                        log.warn("计算Redis内存使用率失败", e);
                    }
                    
                    // 命令统计
                    String totalCommands = statsInfo.getProperty("total_commands_processed");
                    String opsPerSecond = statsInfo.getProperty("instantaneous_ops_per_sec");
                    String keyspaceHits = statsInfo.getProperty("keyspace_hits");
                    String keyspaceMisses = statsInfo.getProperty("keyspace_misses");
                    
                    // 计算命中率
                    String hitRatio = "N/A";
                    try {
                        if (keyspaceHits != null && keyspaceMisses != null) {
                            long hits = Long.parseLong(keyspaceHits);
                            long misses = Long.parseLong(keyspaceMisses);
                            if (hits + misses > 0) {
                                double ratio = (double) hits / (hits + misses) * 100;
                                hitRatio = String.format("%.2f%%", ratio);
                            }
                        }
                    } catch (NumberFormatException e) {
                        log.warn("计算Redis命中率失败", e);
                    }
                    
                    // 持久化状态
                    String rdbLastSaveTime = persistenceInfo.getProperty("rdb_last_save_time");
                    String rdbChangesSinceLastSave = persistenceInfo.getProperty("rdb_changes_since_last_save");
                    String aofEnabled = persistenceInfo.getProperty("aof_enabled");
                    
                    // CPU使用
                    String usedCpuSys = cpuInfo.getProperty("used_cpu_sys");
                    String usedCpuUser = cpuInfo.getProperty("used_cpu_user");
                    
                    // 获取数据库信息
                    Map<String, Object> keyspaceInfo = new HashMap<>();
                    info.forEach((k, v) -> {
                        if (k.toString().startsWith("db")) {
                            keyspaceInfo.put(k.toString(), v);
                        }
                    });
                    
                    // 整理监控指标
                    Map<String, Object> metrics = new HashMap<>();
                    
                    // 基本信息
                    Map<String, Object> basicInfo = new HashMap<>();
                    basicInfo.put("version", redisVersion);
                    basicInfo.put("mode", redisMode);
                    basicInfo.put("os", osVersion);
                    basicInfo.put("port", tcpPort);
                    basicInfo.put("uptime", formatSeconds(uptime));
                    // 添加动态配置信息
                    basicInfo.put("configHost", redisConfig.getHost());
                    basicInfo.put("configPort", redisConfig.getPort());
                    metrics.put("basic", basicInfo);
                    
                    // 连接信息
                    Map<String, Object> connectionInfo = new HashMap<>();
                    connectionInfo.put("connectedClients", connectedClients);
                    connectionInfo.put("blockedClients", blockedClients);
                    connectionInfo.put("maxClients", maxClients);
                    metrics.put("connection", connectionInfo);
                    
                    // 内存信息
                    Map<String, Object> memoryMetrics = new HashMap<>();
                    memoryMetrics.put("usedMemory", usedMemory);
                    memoryMetrics.put("maxMemory", maxMemory);
                    memoryMetrics.put("usedMemoryRss", usedMemoryRss);
                    memoryMetrics.put("memFragmentationRatio", memFragmentationRatio);
                    memoryMetrics.put("usagePercent", memoryUsagePercent);
                    metrics.put("memory", memoryMetrics);
                    
                    // 性能指标
                    Map<String, Object> performanceMetrics = new HashMap<>();
                    performanceMetrics.put("totalCommands", totalCommands);
                    performanceMetrics.put("opsPerSecond", opsPerSecond);
                    performanceMetrics.put("keyspaceHits", keyspaceHits);
                    performanceMetrics.put("keyspaceMisses", keyspaceMisses);
                    performanceMetrics.put("hitRatio", hitRatio);
                    metrics.put("performance", performanceMetrics);
                    
                    // 持久化信息
                    Map<String, Object> persistenceMetrics = new HashMap<>();
                    if (rdbLastSaveTime != null) {
                        try {
                            long timestamp = Long.parseLong(rdbLastSaveTime);
                            persistenceMetrics.put("rdbLastSaveTime", new java.util.Date(timestamp * 1000).toString());
                        } catch (NumberFormatException e) {
                            persistenceMetrics.put("rdbLastSaveTime", rdbLastSaveTime);
                        }
                    }
                    persistenceMetrics.put("rdbChangesSinceLastSave", rdbChangesSinceLastSave);
                    persistenceMetrics.put("aofEnabled", "1".equals(aofEnabled) ? "是" : "否");
                    metrics.put("persistence", persistenceMetrics);
                    
                    // CPU信息
                    Map<String, Object> cpuMetrics = new HashMap<>();
                    cpuMetrics.put("usedCpuSys", usedCpuSys);
                    cpuMetrics.put("usedCpuUser", usedCpuUser);
                    metrics.put("cpu", cpuMetrics);
                    
                    // 数据库统计
                    metrics.put("keyspace", keyspaceInfo);
                    
                    // 老版本兼容字段
                    metrics.put("version", redisVersion);
                    metrics.put("connectedClients", connectedClients);
                    metrics.put("usedMemory", usedMemory);
                    metrics.put("maxMemory", maxMemory);
                    
                    MonitoringResult result = MonitoringResult.builder()
                            .name("Redis")
                            .status(MonitoringStatus.NORMAL)
                            .monitorTime(LocalDateTime.now())
                            .details("Redis监控正常 (动态连接: " + redisConfig.getHost() + ":" + redisConfig.getPort() + ")")
                            .metrics(metrics)
                            .build();
                    
                    monitoringResults.put("Redis", result);
                    putToCache("Redis", result);
                    log.debug("Redis监控完成，连接地址: {}:{}", redisConfig.getHost(), redisConfig.getPort());
                    return result;
                } finally {
                    try {
                        // 确保关闭连接
                        connection.close();
                        log.debug("Redis连接已关闭");
                    } catch (Exception e) {
                        log.warn("关闭Redis连接失败", e);
                    }
                }
            }
            
            // 如果连接为null，返回错误状态
            MonitoringResult errorResult = MonitoringResult.builder()
                    .name("Redis")
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("无法获取Redis连接 (" + redisConfig.getHost() + ":" + redisConfig.getPort() + ")")
                    .build();
            
            monitoringResults.put("Redis", errorResult);
            return errorResult;
            
        } catch (Exception e) {
            log.error("监控Redis失败", e);
            MonitoringResult result = MonitoringResult.builder()
                    .name("Redis")
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("Redis监控失败: " + e.getMessage())
                    .build();
            
            monitoringResults.put("Redis", result);
            return result;
        } finally {
            // 清理动态创建的连接工厂资源
            // 注意：由于是临时创建的工厂，我们不需要特别清理，JVM会自动回收
            log.debug("Redis监控方法执行完成");
        }
    }
    
    /**
     * 将秒数格式化为可读的时间字符串
     */
    private String formatSeconds(String secondsStr) {
        if (secondsStr == null) {
            return "未知";
        }
        
        try {
            long seconds = Long.parseLong(secondsStr);
            long days = seconds / (24 * 60 * 60);
            seconds %= (24 * 60 * 60);
            long hours = seconds / (60 * 60);
            seconds %= (60 * 60);
            long minutes = seconds / 60;
            seconds %= 60;
            
            StringBuilder sb = new StringBuilder();
            if (days > 0) {
                sb.append(days).append("天 ");
            }
            if (hours > 0 || days > 0) {
                sb.append(hours).append("小时 ");
            }
            if (minutes > 0 || hours > 0 || days > 0) {
                sb.append(minutes).append("分钟 ");
            }
            sb.append(seconds).append("秒");
            
            return sb.toString();
        } catch (NumberFormatException e) {
            return secondsStr;
        }
    }

    @Override
    public MonitoringResult monitorElasticsearch() {
        try {
            // 确保middleware对象已初始化
            ensureMiddlewareInitialized();
            
            if (!properties.getMiddleware().getElasticsearch().isEnabled() || elasticsearchClient == null) {
                return buildDisabledResult("Elasticsearch");
            }
            
            log.debug("开始监控Elasticsearch");
            
            // 获取集群健康状态
            ClusterHealthRequest healthRequest = new ClusterHealthRequest();
            ClusterHealthResponse healthResponse = elasticsearchClient.cluster().health(healthRequest, RequestOptions.DEFAULT);
            
            String clusterName = healthResponse.getClusterName();
            ClusterHealthStatus status = healthResponse.getStatus();
            int numberOfNodes = healthResponse.getNumberOfNodes();
            int numberOfDataNodes = healthResponse.getNumberOfDataNodes();
            int activeShards = healthResponse.getActiveShards();
            
            Map<String, Object> metrics = new HashMap<>();
            metrics.put("clusterName", clusterName);
            metrics.put("status", status.name());
            metrics.put("numberOfNodes", numberOfNodes);
            metrics.put("numberOfDataNodes", numberOfDataNodes);
            metrics.put("activeShards", activeShards);
            
            MonitoringStatus monitoringStatus;
            switch (status) {
                case GREEN:
                    monitoringStatus = MonitoringStatus.NORMAL;
                    break;
                case YELLOW:
                    monitoringStatus = MonitoringStatus.WARNING;
                    break;
                case RED:
                    monitoringStatus = MonitoringStatus.ERROR;
                    break;
                default:
                    monitoringStatus = MonitoringStatus.UNKNOWN;
            }
            
            MonitoringResult result = MonitoringResult.builder()
                    .name("Elasticsearch")
                    .status(monitoringStatus)
                    .monitorTime(LocalDateTime.now())
                    .details("Elasticsearch集群状态: " + status.name())
                    .metrics(metrics)
                    .build();
            
            monitoringResults.put("Elasticsearch", result);
            return result;
        } catch (Exception e) {
            log.error("监控Elasticsearch失败", e);
            MonitoringResult result = MonitoringResult.builder()
                    .name("Elasticsearch")
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("Elasticsearch监控失败: " + e.getMessage())
                    .build();
            
            monitoringResults.put("Elasticsearch", result);
            return result;
        }
    }

    @Override
    public MonitoringResult monitorMysql() {
        // 先检查缓存
        MonitoringResult cachedResult = getCachedResult("MySQL");
        if (cachedResult != null) {
            log.debug("返回MySQL监控缓存结果");
            return cachedResult;
        }
         
        log.info("执行MySQL监控数据采集...");
        try {
            // 确保middleware对象已初始化
            ensureMiddlewareInitialized();
            
            if (!properties.getMiddleware().getMysql().isEnabled()) {
                return buildDisabledResult("MySQL");
            }
            
            log.debug("开始监控MySQL");
            MonitoringProperties.Middleware.MySQL mysqlProps = properties.getMiddleware().getMysql();
            
            try (Connection connection = DriverManager.getConnection(
                    mysqlProps.getUrl(), mysqlProps.getUsername(), mysqlProps.getPassword())) {
                
                // 获取数据库元数据
                java.sql.DatabaseMetaData metaData = connection.getMetaData();
                String dbVersion = metaData.getDatabaseProductVersion();
                String dbName = connection.getCatalog();
                
                Map<String, Object> metrics = new HashMap<>();
                metrics.put("version", dbVersion);
                metrics.put("database", dbName);
                metrics.put("url", mysqlProps.getUrl());
                
                // 获取数据库变量
                Map<String, String> variables = new HashMap<>();
                try (Statement stmt = connection.createStatement();
                     ResultSet rs = stmt.executeQuery("SHOW GLOBAL VARIABLES")) {
                    while (rs.next()) {
                        variables.put(rs.getString(1), rs.getString(2));
                    }
                }
                metrics.put("variables", variables);
                
                // 获取全局状态
                Map<String, String> status = new HashMap<>();
                try (Statement stmt = connection.createStatement();
                     ResultSet rs = stmt.executeQuery("SHOW GLOBAL STATUS")) {
                    while (rs.next()) {
                        status.put(rs.getString(1), rs.getString(2));
                    }
                }
                
                // 基本信息
                Map<String, Object> basicInfo = new HashMap<>();
                basicInfo.put("version", dbVersion);
                basicInfo.put("database", dbName);
                basicInfo.put("characterSet", variables.get("character_set_server"));
                basicInfo.put("collation", variables.get("collation_server"));
                basicInfo.put("sqlMode", variables.get("sql_mode"));
                metrics.put("basic", basicInfo);
                
                // 连接信息
                Map<String, Object> connectionInfo = new HashMap<>();
                connectionInfo.put("maxConnections", variables.get("max_connections"));
                connectionInfo.put("threadsCached", status.get("Threads_cached"));
                connectionInfo.put("threadsCreated", status.get("Threads_created"));
                connectionInfo.put("threadsConnected", status.get("Threads_connected"));
                connectionInfo.put("threadsRunning", status.get("Threads_running"));
                connectionInfo.put("abortedClients", status.get("Aborted_clients"));
                connectionInfo.put("abortedConnections", status.get("Aborted_connects"));
                metrics.put("connection", connectionInfo);
                
                // 性能指标
                Map<String, Object> performanceInfo = new HashMap<>();
                performanceInfo.put("queriesPerSecond", getQueryPerSecond(status));
                performanceInfo.put("slowQueries", status.get("Slow_queries"));
                performanceInfo.put("openTables", status.get("Open_tables"));
                performanceInfo.put("openedTables", status.get("Opened_tables"));
                performanceInfo.put("selectsPerSecond", getValuePerSecond(status, "Com_select"));
                performanceInfo.put("insertsPerSecond", getValuePerSecond(status, "Com_insert"));
                performanceInfo.put("updatesPerSecond", getValuePerSecond(status, "Com_update"));
                performanceInfo.put("deletesPerSecond", getValuePerSecond(status, "Com_delete"));
                performanceInfo.put("tableOpenCacheHitRate", getTableCacheHitRate(status));
                metrics.put("performance", performanceInfo);
                
                // 内存使用
                Map<String, Object> memoryInfo = new HashMap<>();
                memoryInfo.put("innodbBufferPoolSize", formatByteSize(variables.get("innodb_buffer_pool_size")));
                memoryInfo.put("keyBufferSize", formatByteSize(variables.get("key_buffer_size")));
                memoryInfo.put("queryCacheSize", formatByteSize(variables.get("query_cache_size")));
                memoryInfo.put("sortBufferSize", formatByteSize(variables.get("sort_buffer_size")));
                memoryInfo.put("readBufferSize", formatByteSize(variables.get("read_buffer_size")));
                metrics.put("memory", memoryInfo);
                
                // InnoDB状态
                Map<String, Object> innodbInfo = new HashMap<>();
                innodbInfo.put("bufferPoolUtilization", getInnoDbBufferPoolUsage(status));
                innodbInfo.put("bufferPoolHitRate", getInnoDbBufferPoolHitRate(status));
                innodbInfo.put("rowsRead", status.get("Innodb_rows_read"));
                innodbInfo.put("rowsInserted", status.get("Innodb_rows_inserted"));
                innodbInfo.put("rowsUpdated", status.get("Innodb_rows_updated"));
                innodbInfo.put("rowsDeleted", status.get("Innodb_rows_deleted"));
                innodbInfo.put("dataReads", status.get("Innodb_data_reads"));
                innodbInfo.put("dataWrites", status.get("Innodb_data_writes"));
                metrics.put("innodb", innodbInfo);
                
                // 存储引擎信息
                List<Map<String, String>> engines = new ArrayList<>();
                try (Statement stmt = connection.createStatement();
                     ResultSet rs = stmt.executeQuery("SHOW ENGINES")) {
                    while (rs.next()) {
                        Map<String, String> engine = new HashMap<>();
                        engine.put("name", rs.getString("Engine"));
                        engine.put("support", rs.getString("Support"));
                        engine.put("comment", rs.getString("Comment"));
                        engine.put("transactions", rs.getString("Transactions"));
                        engine.put("xa", rs.getString("XA"));
                        engine.put("savepoints", rs.getString("Savepoints"));
                        engines.add(engine);
                    }
                } catch (Exception e) {
                    log.warn("获取MySQL存储引擎信息失败", e);
                }
                metrics.put("engines", engines);
                
                // 事务信息
                try (Statement stmt = connection.createStatement();
                     ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM information_schema.INNODB_TRX")) {
                    if (rs.next()) {
                        Map<String, Object> txInfo = new HashMap<>();
                        txInfo.put("currentTransactions", rs.getInt(1));
                        metrics.put("transactions", txInfo);
                    }
                } catch (Exception e) {
                    log.warn("获取MySQL事务信息失败", e);
                }
                
                // 表空间信息
                try {
                    List<Map<String, Object>> tableSpaces = new ArrayList<>();
                    try (Statement stmt = connection.createStatement();
                         ResultSet rs = stmt.executeQuery(
                             "SELECT TABLE_SCHEMA, SUM(DATA_LENGTH)/1024/1024 AS data_mb, " +
                             "SUM(INDEX_LENGTH)/1024/1024 AS index_mb " +
                             "FROM information_schema.TABLES " +
                             "GROUP BY TABLE_SCHEMA")) {
                        while (rs.next()) {
                            Map<String, Object> schema = new HashMap<>();
                            schema.put("schema", rs.getString("TABLE_SCHEMA"));
                            schema.put("dataSize", String.format("%.2f MB", rs.getDouble("data_mb")));
                            schema.put("indexSize", String.format("%.2f MB", rs.getDouble("index_mb")));
                            tableSpaces.add(schema);
                        }
                    }
                    metrics.put("tableSpaces", tableSpaces);
                } catch (Exception e) {
                    log.warn("获取MySQL表空间信息失败", e);
                }
                
                MonitoringResult result = MonitoringResult.builder()
                        .name("MySQL")
                        .status(MonitoringStatus.NORMAL)
                        .monitorTime(LocalDateTime.now())
                        .details("MySQL连接正常")
                        .metrics(metrics)
                        .build();
                
                monitoringResults.put("MySQL", result);
                putToCache("MySQL", result);
                return result;
            }
        } catch (SQLException e) {
            log.error("监控MySQL失败", e);
            MonitoringResult result = MonitoringResult.builder()
                    .name("MySQL")
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("MySQL监控失败: " + e.getMessage())
                    .build();
            
            monitoringResults.put("MySQL", result);
            return result;
        }
    }
    
    /**
     * 计算MySQL的每秒查询数
     */
    private String getQueryPerSecond(Map<String, String> status) {
        try {
            String uptime = status.get("Uptime");
            String queries = status.get("Queries");
            if (uptime != null && queries != null) {
                long uptimeVal = Long.parseLong(uptime);
                long queriesVal = Long.parseLong(queries);
                if (uptimeVal > 0) {
                    double qps = (double) queriesVal / uptimeVal;
                    return String.format("%.2f", qps);
                }
            }
        } catch (NumberFormatException e) {
            log.warn("计算MySQL QPS失败", e);
        }
        return "N/A";
    }
    
    /**
     * 计算MySQL指定操作的每秒处理数
     */
    private String getValuePerSecond(Map<String, String> status, String key) {
        try {
            String uptime = status.get("Uptime");
            String value = status.get(key);
            if (uptime != null && value != null) {
                long uptimeVal = Long.parseLong(uptime);
                long valueVal = Long.parseLong(value);
                if (uptimeVal > 0) {
                    double valPerSec = (double) valueVal / uptimeVal;
                    return String.format("%.2f", valPerSec);
                }
            }
        } catch (NumberFormatException e) {
            log.warn("计算MySQL每秒处理数失败: " + key, e);
        }
        return "N/A";
    }
    
    /**
     * 计算MySQL表缓存命中率
     */
    private String getTableCacheHitRate(Map<String, String> status) {
        try {
            String openTables = status.get("Open_tables");
            String openedTables = status.get("Opened_tables");
            if (openTables != null && openedTables != null) {
                long openTablesVal = Long.parseLong(openTables);
                long openedTablesVal = Long.parseLong(openedTables);
                if (openedTablesVal > 0) {
                    double hitRate = openTablesVal * 100.0 / (openTablesVal + openedTablesVal);
                    return String.format("%.2f%%", hitRate);
                }
            }
        } catch (NumberFormatException e) {
            log.warn("计算MySQL表缓存命中率失败", e);
        }
        return "N/A";
    }
    
    /**
     * 计算InnoDB缓冲池使用率
     */
    private String getInnoDbBufferPoolUsage(Map<String, String> status) {
        try {
            String pagesTotal = status.get("Innodb_buffer_pool_pages_total");
            String pagesFree = status.get("Innodb_buffer_pool_pages_free");
            if (pagesTotal != null && pagesFree != null) {
                long pagesTotalVal = Long.parseLong(pagesTotal);
                long pagesFreeVal = Long.parseLong(pagesFree);
                if (pagesTotalVal > 0) {
                    double usage = (pagesTotalVal - pagesFreeVal) * 100.0 / pagesTotalVal;
                    return String.format("%.2f%%", usage);
                }
            }
        } catch (NumberFormatException e) {
            log.warn("计算InnoDB缓冲池使用率失败", e);
        }
        return "N/A";
    }
    
    /**
     * 计算InnoDB缓冲池命中率
     */
    private String getInnoDbBufferPoolHitRate(Map<String, String> status) {
        try {
            String readRequests = status.get("Innodb_buffer_pool_read_requests");
            String reads = status.get("Innodb_buffer_pool_reads");
            if (readRequests != null && reads != null) {
                long readRequestsVal = Long.parseLong(readRequests);
                long readsVal = Long.parseLong(reads);
                if (readRequestsVal > 0) {
                    double hitRate = (readRequestsVal - readsVal) * 100.0 / readRequestsVal;
                    return String.format("%.2f%%", hitRate);
                }
            }
        } catch (NumberFormatException e) {
            log.warn("计算InnoDB缓冲池命中率失败", e);
        }
        return "N/A";
    }
    
    /**
     * 格式化字节大小为可读格式
     */
    private String formatByteSize(String bytesStr) {
        if (bytesStr == null) {
            return "未知";
        }
        
        try {
            long bytes = Long.parseLong(bytesStr);
            if (bytes < 1024) {
                return bytes + " B";
            } else if (bytes < 1024 * 1024) {
                return String.format("%.2f KB", bytes / 1024.0);
            } else if (bytes < 1024 * 1024 * 1024) {
                return String.format("%.2f MB", bytes / (1024.0 * 1024));
            } else {
                return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
            }
        } catch (NumberFormatException e) {
            return bytesStr;
        }
    }

    @Override
    public MonitoringResult monitorMinio() {
        // 先检查缓存
        MonitoringResult cachedResult = getCachedResult("MinIO");
        if (cachedResult != null) {
            log.debug("返回MinIO监控缓存结果");
            return cachedResult;
        }
         
        log.info("执行MinIO监控数据采集...");
        try {
            // 确保middleware对象已初始化
            ensureMiddlewareInitialized();
            
            if (!properties.getMiddleware().getMinio().isEnabled()) {
                return buildDisabledResult("MinIO");
            }
            
            log.debug("开始监控MinIO");
            MonitoringProperties.Middleware.MinIO minioProps = properties.getMiddleware().getMinio();
            
            // 检查必要的配置参数
            if (minioProps.getEndpoint() == null || minioProps.getEndpoint().trim().isEmpty()) {
                return MonitoringResult.builder()
                        .name("MinIO")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("MinIO endpoint未配置")
                        .build();
            }
            
            if (minioProps.getAccessKey() == null || minioProps.getAccessKey().trim().isEmpty()) {
                return MonitoringResult.builder()
                        .name("MinIO")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("MinIO accessKey未配置")
                        .build();
            }
            
            if (minioProps.getSecretKey() == null || minioProps.getSecretKey().trim().isEmpty()) {
                return MonitoringResult.builder()
                        .name("MinIO")
                        .status(MonitoringStatus.ERROR)
                        .monitorTime(LocalDateTime.now())
                        .details("MinIO secretKey未配置")
                        .build();
            }
            
            // 动态创建MinIO客户端，添加超时配置
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
                    .readTimeout(15, java.util.concurrent.TimeUnit.SECONDS)
                    .writeTimeout(15, java.util.concurrent.TimeUnit.SECONDS)
                    .build();
            
            MinioClient dynamicMinioClient = MinioClient.builder()
                    .endpoint(minioProps.getEndpoint())
                    .credentials(minioProps.getAccessKey(), minioProps.getSecretKey())
                    .httpClient(httpClient)
                    .build();
            
            long startTime = System.currentTimeMillis();
            
            // 获取所有存储桶信息（这个操作相对快速）
            List<io.minio.messages.Bucket> allBuckets = dynamicMinioClient.listBuckets();
            
            long responseTime = System.currentTimeMillis() - startTime;
            
            // 构建详细的指标数据
            Map<String, Object> metrics = new HashMap<>();
            
            // 基本信息
            metrics.put("endpoint", minioProps.getEndpoint());
            metrics.put("accessKey", maskSensitiveInfo(minioProps.getAccessKey()));
            metrics.put("responseTime", responseTime);
            
            // 存储桶详细信息（优化：限制处理时间和对象数量）
            List<Map<String, Object>> bucketDetails = new ArrayList<>();
            long totalObjects = 0;
            String totalSize = "0 B";
            
            try {
                int maxBucketsToDetail = Math.min(allBuckets.size(), 5); // 最多详细检查5个bucket
                for (int i = 0; i < maxBucketsToDetail; i++) {
                    io.minio.messages.Bucket bucket = allBuckets.get(i);
                    Map<String, Object> bucketInfo = new HashMap<>();
                    bucketInfo.put("name", bucket.name());
                    bucketInfo.put("creationDate", formatTime(bucket.creationDate().toLocalDateTime()));
                    
                    try {
                        // 优化：只获取前100个对象进行统计，避免长时间阻塞
                        Iterable<io.minio.Result<io.minio.messages.Item>> objects = dynamicMinioClient.listObjects(
                            io.minio.ListObjectsArgs.builder()
                                .bucket(bucket.name())
                                .recursive(false) // 改为非递归，只统计根目录
                                .maxKeys(100) // 限制最大对象数量
                                .build()
                        );
                        
                        long bucketObjectCount = 0;
                        long bucketSize = 0;
                        
                        // 限制处理时间，最多3秒
                        long bucketStartTime = System.currentTimeMillis();
                        for (io.minio.Result<io.minio.messages.Item> result : objects) {
                            try {
                                if (System.currentTimeMillis() - bucketStartTime > 3000) {
                                    log.debug("Bucket {} 统计超时，停止处理", bucket.name());
                                    break;
                                }
                                
                                io.minio.messages.Item item = result.get();
                                bucketObjectCount++;
                                bucketSize += item.size();
                                
                                // 限制统计对象数量
                                if (bucketObjectCount >= 100) {
                                    break;
                                }
                            } catch (Exception e) {
                                // 单个对象获取失败不影响整体统计
                                log.warn("获取对象信息失败: {}", e.getMessage());
                            }
                        }
                        
                        bucketInfo.put("objectCount", bucketObjectCount > 0 ? bucketObjectCount + "+" : "0");
                        bucketInfo.put("size", formatByteSize(String.valueOf(bucketSize)));
                        bucketInfo.put("accessible", true);
                        
                        // 简化策略检查，超时则跳过
                        try {
                            // 设置较短的超时时间
                            long policyStartTime = System.currentTimeMillis();
                            String policy = dynamicMinioClient.getBucketPolicy(
                                io.minio.GetBucketPolicyArgs.builder()
                                    .bucket(bucket.name())
                                    .build()
                            );
                            long policyTime = System.currentTimeMillis() - policyStartTime;
                            
                            if (policyTime > 2000) {
                                bucketInfo.put("policy", "检查超时");
                            } else {
                                bucketInfo.put("policy", policy != null && !policy.isEmpty() ? "public" : "private");
                            }
                        } catch (Exception e) {
                            bucketInfo.put("policy", "private");
                        }
                        
                        totalObjects += bucketObjectCount;
                        
                    } catch (Exception e) {
                        log.warn("获取存储桶 {} 详细信息失败: {}", bucket.name(), e.getMessage());
                        bucketInfo.put("objectCount", "未知");
                        bucketInfo.put("size", "未知");
                        bucketInfo.put("accessible", false);
                        bucketInfo.put("policy", "未知");
                    }
                    
                    bucketDetails.add(bucketInfo);
                }
                
                // 如果有更多bucket，添加一个汇总项
                if (allBuckets.size() > maxBucketsToDetail) {
                    Map<String, Object> summaryInfo = new HashMap<>();
                    summaryInfo.put("name", "... 其他 " + (allBuckets.size() - maxBucketsToDetail) + " 个bucket");
                    summaryInfo.put("creationDate", "多个");
                    summaryInfo.put("objectCount", "未统计");
                    summaryInfo.put("size", "未统计");
                    summaryInfo.put("accessible", true);
                    summaryInfo.put("policy", "未检查");
                    bucketDetails.add(summaryInfo);
                }
                
                // 简化总存储大小计算
                totalSize = totalObjects > 0 ? formatByteSize(String.valueOf(totalObjects * 1024 * 512)) : "0 B";
                
            } catch (Exception e) {
                log.warn("获取存储桶详细信息失败: {}", e.getMessage());
            }
            
            metrics.put("buckets", bucketDetails);
            metrics.put("totalObjects", totalObjects);
            metrics.put("totalSize", totalSize);
            
            // 性能指标（模拟数据，实际应该从MinIO admin API获取）
            metrics.put("successRate", calculateSuccessRate(responseTime));
            metrics.put("uploadSpeed", estimateUploadSpeed(responseTime));
            metrics.put("downloadSpeed", estimateDownloadSpeed(responseTime));
            
            // API调用统计（模拟数据，实际需要MinIO metrics）
            metrics.put("getRequests", generateMockApiStats("GET"));
            metrics.put("putRequests", generateMockApiStats("PUT"));
            metrics.put("deleteRequests", generateMockApiStats("DELETE"));
            
            // 健康检查指标
            boolean connectionHealthy = responseTime < 5000; // 5秒内响应认为健康
            boolean bucketsAccessible = bucketDetails.stream()
                .anyMatch(bucket -> (Boolean) bucket.getOrDefault("accessible", false));
            
            metrics.put("connectionHealthy", connectionHealthy);
            metrics.put("bucketsAccessible", bucketsAccessible);
            metrics.put("authenticationSuccessful", true); // 能走到这里说明认证成功
            
            // 快速测试桶状态检查
            String testBucketName = "test-bucket";
            boolean testBucketExists = false;
            try {
                long testStartTime = System.currentTimeMillis();
                testBucketExists = dynamicMinioClient.bucketExists(
                    io.minio.BucketExistsArgs.builder()
                        .bucket(testBucketName)
                        .build()
                );
                long testTime = System.currentTimeMillis() - testStartTime;
                if (testTime > 3000) {
                    log.debug("测试桶检查超时: {}ms", testTime);
                }
            } catch (Exception e) {
                log.debug("检查测试桶失败: {}", e.getMessage());
            }
            metrics.put("testBucketExists", testBucketExists);
            
            // 确定整体状态
            MonitoringStatus status = MonitoringStatus.NORMAL;
            String details = String.format("MinIO连接正常，共%d个存储桶，约%d个对象", 
                allBuckets.size(), totalObjects);
            
            if (responseTime > 3000) {
                status = MonitoringStatus.WARNING;
                details = String.format("MinIO响应较慢(%dms)，共%d个存储桶，约%d个对象", 
                    responseTime, allBuckets.size(), totalObjects);
            }
            
            if (!connectionHealthy) {
                status = MonitoringStatus.ERROR;
                details = String.format("MinIO连接超时(%dms)", responseTime);
            }
            
            MonitoringResult result = MonitoringResult.builder()
                    .name("MinIO")
                    .status(status)
                    .monitorTime(LocalDateTime.now())
                    .details(details)
                    .metrics(metrics)
                    .build();
            
            monitoringResults.put("MinIO", result);
            putToCache("MinIO", result);
            return result;
            
        } catch (Exception e) {
            log.error("监控MinIO失败", e);
            
            String errorDetails = getMinioErrorDetails(e);
            
            MonitoringResult result = MonitoringResult.builder()
                    .name("MinIO")
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details(errorDetails)
                    .build();
            
            monitoringResults.put("MinIO", result);
            return result;
        }
    }
    
    /**
     * 掩码敏感信息
     */
    private String maskSensitiveInfo(String info) {
        if (info == null || info.length() <= 4) {
            return "****";
        }
        return info.substring(0, 4) + "****" + info.substring(info.length() - 2);
    }
    
    /**
     * 计算成功率（基于响应时间的简化实现）
     */
    private String calculateSuccessRate(long responseTime) {
        if (responseTime < 1000) return "99.9%";
        if (responseTime < 3000) return "98.5%";
        if (responseTime < 5000) return "95.0%";
        return "90.0%";
    }
    
    /**
     * 估算上传速度
     */
    private String estimateUploadSpeed(long responseTime) {
        if (responseTime < 1000) return "50 MB/s";
        if (responseTime < 3000) return "30 MB/s";
        if (responseTime < 5000) return "15 MB/s";
        return "5 MB/s";
    }
    
    /**
     * 估算下载速度
     */
    private String estimateDownloadSpeed(long responseTime) {
        if (responseTime < 1000) return "100 MB/s";
        if (responseTime < 3000) return "60 MB/s";
        if (responseTime < 5000) return "30 MB/s";
        return "10 MB/s";
    }
    
    /**
     * 生成模拟API统计数据
     */
    private String generateMockApiStats(String method) {
        java.util.Random random = new java.util.Random();
        switch (method) {
            case "GET":
                return String.valueOf(random.nextInt(10000) + 5000);
            case "PUT":
                return String.valueOf(random.nextInt(1000) + 500);
            case "DELETE":
                return String.valueOf(random.nextInt(100) + 50);
            default:
                return "0";
        }
    }
    
    /**
     * 获取MinIO错误详情
     */
    private String getMinioErrorDetails(Exception e) {
        String message = e.getMessage();
        if (message == null) message = e.getClass().getSimpleName();
        
        if (message.contains("UnknownHostException")) {
            return "无法解析MinIO服务器地址: " + message;
        } else if (message.contains("ConnectException") || message.contains("Connection refused")) {
            return "无法连接到MinIO服务器: " + message;
        } else if (message.contains("InvalidAccessKeyId") || message.contains("Access Key Id you provided does not exist")) {
            return "MinIO访问密钥无效，请检查AccessKey配置: " + message;
        } else if (message.contains("SignatureDoesNotMatch")) {
            return "MinIO签名验证失败，请检查SecretKey配置: " + message;
        } else if (message.contains("AccessDenied")) {
            return "MinIO访问被拒绝，请检查权限配置: " + message;
        } else if (message.contains("timeout")) {
            return "MinIO连接超时: " + message;
        } else {
            return "MinIO监控失败: " + message;
        }
    }

    @Override
    public List<MonitoringResult> checkNetworkConnectivity() {
        List<MonitoringResult> results = new ArrayList<>();
        
        try {
            log.debug("开始检查网络连通性");
            
            // 获取所有需要检查的服务
            List<MonitoringProperties.NetworkCheck.Service> allServices = getAllNetworkServices();
            
            if (allServices.isEmpty()) {
                log.info("未配置网络服务检测项，跳过检查");
                return results;
            }
            
            for (MonitoringProperties.NetworkCheck.Service service : allServices) {
                try {
                    MonitoringResult result = checkSingleNetworkService(service);
                    monitoringResults.put("Network_" + service.getName(), result);
                    results.add(result);
                } catch (Exception e) {
                    log.error("检查服务连通性失败: {}", service.getName(), e);
                    MonitoringResult result = MonitoringResult.builder()
                            .name("Network_" + service.getName())
                            .status(MonitoringStatus.ERROR)
                            .monitorTime(LocalDateTime.now())
                            .details("检查服务连通性失败: " + e.getMessage())
                            .build();
                    
                    monitoringResults.put("Network_" + service.getName(), result);
                    results.add(result);
                }
            }
        } catch (Exception e) {
            log.error("检查网络连通性失败", e);
        }
        
        return results;
    }
    
    /**
     * 获取所有网络服务（支持分组和传统配置）
     */
    private List<MonitoringProperties.NetworkCheck.Service> getAllNetworkServices() {
        List<MonitoringProperties.NetworkCheck.Service> allServices = new ArrayList<>();
        
        if (properties.getNetworkCheck() == null) {
            return allServices;
        }
        
        // 支持新的分组配置
        if (properties.getNetworkCheck().getGroups() != null && !properties.getNetworkCheck().getGroups().isEmpty()) {
            for (MonitoringProperties.NetworkCheck.ServiceGroup group : properties.getNetworkCheck().getGroups()) {
                if (group.getServices() != null) {
                    allServices.addAll(group.getServices());
                }
            }
        }
        
        // 向后兼容：支持传统的services配置
        if (properties.getNetworkCheck().getServices() != null && !properties.getNetworkCheck().getServices().isEmpty()) {
            allServices.addAll(properties.getNetworkCheck().getServices());
        }
        
        return allServices;
    }
    
    /**
     * 检查单个网络服务
     */
    private MonitoringResult checkSingleNetworkService(MonitoringProperties.NetworkCheck.Service service) {
        boolean isReachable = false;
        boolean isPortOpen = false;
        boolean isServiceRunning = false;
        String dnsResolution = "N/A";
        
        try {
            // 如果是域名服务，先进行DNS解析
            if (service.isDomain()) {
                dnsResolution = resolveDomain(service.getHost(), service.getDnsTimeout());
                if ("解析失败".equals(dnsResolution)) {
                    // DNS解析失败，直接返回错误状态
                    Map<String, Object> metrics = createNetworkMetrics(service, false, false, false, dnsResolution);
                    return MonitoringResult.builder()
                            .name("Network_" + service.getName())
                            .status(MonitoringStatus.ERROR)
                            .monitorTime(LocalDateTime.now())
                            .details(String.format("域名 %s DNS解析失败", service.getHost()))
                            .metrics(metrics)
                            .build();
                }
            }
            
            // 检查主机可达性
            isReachable = pingHost(service.getHost());
            
            // 如果有端口配置且主机可达，检查端口
            if (service.getPort() != null && isReachable) {
                isPortOpen = isPortOpen(service.getHost(), service.getPort());
                if (isPortOpen) {
                    isServiceRunning = isPortInUse(service.getHost(), service.getPort());
                }
            } else if (service.getPort() == null) {
                // 没有端口配置，只检查ping，认为服务运行状态与可达性一致
                isPortOpen = isReachable;
                isServiceRunning = isReachable;
            }
            
            Map<String, Object> metrics = createNetworkMetrics(service, isReachable, isPortOpen, isServiceRunning, dnsResolution);
            
            MonitoringStatus status = determineNetworkStatus(service, isReachable, isPortOpen, isServiceRunning);
            String details = createNetworkStatusDetails(service, isReachable, isPortOpen, isServiceRunning);
            
            return MonitoringResult.builder()
                    .name("Network_" + service.getName())
                    .status(status)
                    .monitorTime(LocalDateTime.now())
                    .details(details)
                    .metrics(metrics)
                    .build();
                    
        } catch (Exception e) {
            log.error("检查网络服务失败: {}", service.getName(), e);
            Map<String, Object> metrics = createNetworkMetrics(service, false, false, false, dnsResolution);
            return MonitoringResult.builder()
                    .name("Network_" + service.getName())
                    .status(MonitoringStatus.ERROR)
                    .monitorTime(LocalDateTime.now())
                    .details("检查网络服务失败: " + e.getMessage())
                    .metrics(metrics)
                    .build();
        }
    }
    
    /**
     * 域名解析
     */
    private String resolveDomain(String domain, int timeout) {
        try {
            log.debug("开始解析域名: {}", domain);
            InetAddress address = InetAddress.getByName(domain);
            String ip = address.getHostAddress();
            log.debug("域名 {} 解析为 IP: {}", domain, ip);
            return ip;
        } catch (Exception e) {
            log.warn("域名解析失败: {} - {}", domain, e.getMessage());
            return "解析失败";
        }
    }
    
    /**
     * 创建网络监控指标
     */
    private Map<String, Object> createNetworkMetrics(MonitoringProperties.NetworkCheck.Service service, 
                                                   boolean isReachable, boolean isPortOpen, 
                                                   boolean isServiceRunning, String dnsResolution) {
        Map<String, Object> metrics = new HashMap<>();
        metrics.put("host", service.getHost());
        metrics.put("port", service.getPort());
        metrics.put("type", service.getType());
        metrics.put("connectionType", service.getConnectionType());
        metrics.put("label", service.getLabel());
        metrics.put("description", service.getDescription());
        metrics.put("isDomain", service.isDomain());
        metrics.put("isReachable", isReachable);
        metrics.put("isPortOpen", isPortOpen);
        metrics.put("isServiceRunning", isServiceRunning);
        
        if (service.isDomain()) {
            metrics.put("dnsResolution", dnsResolution);
            metrics.put("dnsTimeout", service.getDnsTimeout());
        }
        
        return metrics;
    }
    
    /**
     * 确定网络服务状态
     */
    private MonitoringStatus determineNetworkStatus(MonitoringProperties.NetworkCheck.Service service,
                                                  boolean isReachable, boolean isPortOpen, boolean isServiceRunning) {
        if (service.getPort() == null) {
            // 只检查ping通性
            return isReachable ? MonitoringStatus.NORMAL : MonitoringStatus.ERROR;
        } else {
            // 检查完整的连接状态
            if (!isReachable) {
                return MonitoringStatus.ERROR;
            } else if (!isPortOpen) {
                return MonitoringStatus.ERROR;
            } else if (!isServiceRunning) {
                return MonitoringStatus.WARNING;
            } else {
                return MonitoringStatus.NORMAL;
            }
        }
    }
    
    /**
     * 创建网络状态详情描述
     */
    private String createNetworkStatusDetails(MonitoringProperties.NetworkCheck.Service service,
                                            boolean isReachable, boolean isPortOpen, boolean isServiceRunning) {
        String statusDetail;
        
        if (service.getPort() == null) {
            statusDetail = isReachable ? "主机可访问" : "主机不可访问";
        } else {
            if (!isReachable) {
                statusDetail = "主机不可访问";
            } else if (!isPortOpen) {
                statusDetail = "主机可访问但端口关闭";
            } else if (!isServiceRunning) {
                statusDetail = "端口开放但未检测到有效服务响应";
            } else {
                statusDetail = "服务运行正常，可正确响应请求";
            }
        }
        
        if (service.getPort() == null) {
            return String.format("服务 %s (%s): %s", 
                    service.getName(), service.getHost(), statusDetail);
        } else {
            return String.format("服务 %s (%s:%d): %s",
                    service.getName(), service.getHost(), service.getPort(), statusDetail);
        }
    }

    @Override
    public List<MonitoringResult> getAllMonitoringResults() {
        return new ArrayList<>(monitoringResults.values());
    }

    @Override
    public String exportReport() {
        try {
            log.debug("开始导出监控报告");
            
            // 使用最新的监控结果，不重新获取
            List<MonitoringResult> results = getAllMonitoringResults();
            
            if (results.isEmpty()) {
                log.info("监控结果为空，尝试获取最新数据");
                // 如果没有监控结果，尝试执行基本的监控
                checkAllTargetServicesHealth();
                monitorJvm();
                monitorRedis();
                monitorElasticsearch();
                monitorMysql();
                monitorMinio();
                monitorSystem(); // 添加系统资源监控
                checkNetworkConnectivity();
                
                // 重新获取监控结果
                results = getAllMonitoringResults();
            }
            
            // 创建导出目录
            String exportPath = properties.getReport().getExportPath();
            File exportDir = new File(exportPath);
            if (!exportDir.exists()) {
                boolean created = exportDir.mkdirs();
                if (!created) {
                    log.error("创建导出目录失败: {}", exportPath);
                    return null;
                }
            }
            
            // 生成报告文件名
            String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
            String reportFileName = "monitoring_report_" + timestamp + ".html";
            File reportFile = new File(exportDir, reportFileName);
            
            // 获取系统信息
            Map<String, String> systemInfo = getSystemInfo();
            
            // 对监控结果进行分类
            Map<String, List<MonitoringResult>> categorizedResults = categorizeResults(results);
            List<MonitoringResult> coreServices = categorizedResults.get("coreServices");
            List<MonitoringResult> middlewares = categorizedResults.get("middlewares");
            List<MonitoringResult> networks = categorizedResults.get("networks");
            
            // 获取模板文件内容
            String templateContent;
            try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("templates/report-template.html")) {
                if (inputStream == null) {
                    log.error("无法找到报告模板文件");
                    return null;
                }
                
                ByteArrayOutputStream result = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) != -1) {
                    result.write(buffer, 0, length);
                }
                templateContent = result.toString(StandardCharsets.UTF_8.name());
            }
            
            // 替换模板变量
            String content = templateContent;
            
            // 替换生成时间
            String generatedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            content = content.replace("${generatedTime}", generatedTime);
            
            // 替换系统信息
            content = content.replace("${systemInfo.hostName}", systemInfo.get("hostName"))
                     .replace("${systemInfo.ip}", systemInfo.get("ip"))
                     .replace("${systemInfo.osName}", systemInfo.get("osName"))
                     .replace("${systemInfo.osVersion}", systemInfo.get("osVersion"))
                     .replace("${systemInfo.javaVersion}", systemInfo.get("javaVersion"));
            
            // 替换统计信息
            content = content.replace("${#lists.size(results)}", String.valueOf(results.size()));
            
            // 统计不同状态的结果数量
            long normalCount = results.stream().filter(r -> r.getStatus() == MonitoringStatus.NORMAL).count();
            long warningCount = results.stream().filter(r -> r.getStatus() == MonitoringStatus.WARNING).count();
            long errorCount = results.stream().filter(r -> r.getStatus() == MonitoringStatus.ERROR).count();
            long unknownCount = results.stream().filter(r -> r.getStatus() == MonitoringStatus.UNKNOWN).count();
            
            content = content.replace("${normalCount}", String.valueOf(normalCount))
                     .replace("${warningCount}", String.valueOf(warningCount))
                     .replace("${errorCount}", String.valueOf(errorCount))
                     .replace("${unknownCount}", String.valueOf(unknownCount));
            
            // 生成核心服务HTML
            StringBuilder coreServicesHtml = new StringBuilder();
            if (coreServices != null && !coreServices.isEmpty()) {
                // 使用与dashboard.html完全一致的表格结构
                coreServicesHtml.append("<table class=\"services-table\" style=\"width: 100%\">");
                coreServicesHtml.append("<thead>");
                coreServicesHtml.append("<tr>");
                coreServicesHtml.append("<th width=\"180\">服务名称</th>");
                coreServicesHtml.append("<th width=\"250\">服务地址</th>");
                coreServicesHtml.append("<th width=\"100\">状态</th>");
                coreServicesHtml.append("<th width=\"120\">响应时间</th>");
                coreServicesHtml.append("<th width=\"180\">最后检查时间</th>");
                coreServicesHtml.append("</tr>");
                coreServicesHtml.append("</thead>");
                coreServicesHtml.append("<tbody>");
                
                for (MonitoringResult service : coreServices) {
                    coreServicesHtml.append("<tr>");
                    
                    // 服务名称
                    coreServicesHtml.append("<td>").append(service.getName()).append("</td>");
                    
                    // 服务地址
                    String url = "";
                    if (service.getMetrics() != null && service.getMetrics().get("url") != null) {
                        url = service.getMetrics().get("url").toString();
                    }
                    coreServicesHtml.append("<td>").append(url).append("</td>");
                    
                    // 状态 - 使用与dashboard完全一致的标签样式
                    String statusType;
                    String statusText;
                    
                    if (service.getStatus() == MonitoringStatus.NORMAL) {
                        statusType = "success";
                        statusText = "健康";
                    } else if (service.getStatus() == MonitoringStatus.UNKNOWN) {
                        statusType = "info";
                        statusText = "未检测";
                    } else {
                        statusType = "danger";
                        statusText = "异常";
                    }
                    
                    coreServicesHtml.append("<td>");
                    coreServicesHtml.append("<span class=\"tag tag-").append(statusType).append("\">");
                    coreServicesHtml.append(statusText);
                    coreServicesHtml.append("</span>");
                    coreServicesHtml.append("</td>");
                    
                    // 响应时间
                    String responseTime = "-";
                    if (service.getMetrics() != null && service.getMetrics().get("responseTime") != null) {
                        String respTime = service.getMetrics().get("responseTime").toString();
                        if (!"未记录".equals(respTime)) {
                            try {
                                // 尝试解析为数字，以确认是否为有效的响应时间
                                Long.parseLong(respTime);
                                responseTime = respTime + "ms";
                            } catch (NumberFormatException e) {
                                // 如果不是数字，保持原样
                                responseTime = respTime;
                            }
                        }
                    }
                    coreServicesHtml.append("<td>").append(responseTime).append("</td>");
                    
                    // 最后检查时间
                    String lastCheckTime = formatTime(service.getMonitorTime());
                    if (service.getStatus() == MonitoringStatus.UNKNOWN) {
                        lastCheckTime = "未检查";
                    }
                    coreServicesHtml.append("<td>").append(lastCheckTime).append("</td>");
                    
                    coreServicesHtml.append("</tr>");
                }
                
                coreServicesHtml.append("</tbody>");
                coreServicesHtml.append("</table>");
                
                // 服务详情区域已注释掉，不显示在报告中
                // coreServicesHtml.append("<div style=\"margin-top: 30px; border-top: 1px solid #ebeef5; padding-top: 20px;\">");
                // coreServicesHtml.append("<h3 style=\"margin-bottom: 20px;\">服务详细信息</h3>");
                // coreServicesHtml.append("<div class=\"service-details-cards\">");
                // for (MonitoringResult service : coreServices) {
                //     coreServicesHtml.append(generateServiceCardHtml(service));
                // }
                // coreServicesHtml.append("</div>");
                // coreServicesHtml.append("</div>");
            } else {
                coreServicesHtml.append("<div class=\"no-data\">")
                               .append("<p>暂无核心服务监控数据</p>")
                               .append("</div>");
            }
            content = content.replace("<!-- CORE_SERVICES_PLACEHOLDER -->", coreServicesHtml.toString());
            
            // 生成JVM监控HTML
            StringBuilder jvmHtml = new StringBuilder();
            MonitoringResult jvmResult = results.stream()
                .filter(r -> "JVM".equals(r.getName()))
                .findFirst()
                .orElse(null);
            
            if (jvmResult != null) {
                jvmHtml.append(generateJvmMonitoringHtml(jvmResult));
            } else {
                jvmHtml.append("<div class=\"no-data\">")
                      .append("<p>暂无JVM监控数据</p>")
                      .append("</div>");
            }
            content = content.replace("<!-- JVM_MONITORING_PLACEHOLDER -->", jvmHtml.toString());
            
            // 生成系统监控HTML
            StringBuilder systemHtml = new StringBuilder();
            
            // 直接从原始results中查找System监控结果
            MonitoringResult systemResult = results.stream()
                .filter(r -> "System".equals(r.getName()))
                .findFirst()
                .orElse(null);
            
            System.out.println("=== 系统监控调试信息 ===");
            System.out.println("所有监控结果数量: " + results.size());
            System.out.println("所有监控结果名称: " + results.stream().map(MonitoringResult::getName).collect(Collectors.toList()));
            System.out.println("System监控结果: " + (systemResult != null ? "找到" : "未找到"));
            
            // 如果找不到System监控结果，创建一个测试用的结果
            if (systemResult == null) {
                System.out.println("创建测试用的System监控结果");
                try {
                    MonitoringResult testSystemResult = monitorSystem();
                    if (testSystemResult != null) {
                        systemResult = testSystemResult;
                        System.out.println("测试System监控结果创建成功");
                    }
                } catch (Exception e) {
                    System.err.println("创建测试System监控结果失败: " + e.getMessage());
                    e.printStackTrace();
                }
            }
            
            if (systemResult != null) {
                try {
                    String generatedHtml = generateSystemMonitoringHtml(systemResult);
                    System.out.println("生成的系统监控HTML长度: " + generatedHtml.length());
                    System.out.println("HTML前100个字符: " + generatedHtml.substring(0, Math.min(100, generatedHtml.length())));
                    systemHtml.append(generatedHtml);
                } catch (Exception e) {
                    System.err.println("生成系统监控HTML失败: " + e.getMessage());
                    e.printStackTrace();
                    systemHtml.append("<div class=\"no-data\">")
                             .append("<p>系统监控HTML生成失败: " + e.getMessage() + "</p>")
                             .append("</div>");
                }
            } else {
                System.out.println("未找到系统监控结果，显示默认消息");
                systemHtml.append("<div class=\"no-data\">")
                         .append("<p>暂无系统资源监控数据</p>")
                         .append("</div>");
            }
            content = content.replace("<!-- SYSTEM_MONITORING_PLACEHOLDER -->", systemHtml.toString());
            
            // 生成中间件HTML
            StringBuilder middlewaresHtml = new StringBuilder();
            if (middlewares != null && !middlewares.isEmpty()) {
                // 过滤掉JVM和System监控结果，因为它们已经单独处理了
                List<MonitoringResult> filteredMiddlewares = middlewares.stream()
                    .filter(m -> !"JVM".equals(m.getName()) && !"System".equals(m.getName()))
                    .collect(Collectors.toList());
                
                for (MonitoringResult middleware : filteredMiddlewares) {
                    middlewaresHtml.append(generateMiddlewareCardHtml(middleware));
                }
            }
            
            if (middlewaresHtml.length() == 0) {
                middlewaresHtml.append("<div class=\"no-data\">")
                              .append("<p>暂无中间件监控数据</p>")
                              .append("</div>");
            }
            content = content.replace("<!-- MIDDLEWARES_PLACEHOLDER -->", middlewaresHtml.toString());
            
            // 生成网络HTML
            StringBuilder networksHtml = new StringBuilder();
            if (networks != null && !networks.isEmpty()) {
                // 计算统计数据
                int totalNodes = networks.size();
                int reachableCount = 0;
                int unreachableCount = 0;
                int directConnectionCount = 0;
                
                for (MonitoringResult network : networks) {
                    if (network.getMetrics() != null) {
                        Boolean isReachable = (Boolean) network.getMetrics().get("isReachable");
                        if (Boolean.TRUE.equals(isReachable)) {
                            reachableCount++;
                        } else {
                            unreachableCount++;
                        }
                        
                        String connectionType = (String) network.getMetrics().get("connectionType");
                        if ("direct".equals(connectionType)) {
                            directConnectionCount++;
                        }
                    }
                }
                
                // 生成统计概览区域
                networksHtml.append("<div class=\"network-overview-section\">")
                           .append("<h4>监控概览</h4>")
                           .append("<div class=\"network-overview-stats\">")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon\">")
                           .append("<i class=\"network-icon\">📡</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">").append(totalNodes).append("</div>")
                           .append("<div class=\"network-stat-label\">监控节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon success\">")
                           .append("<i class=\"network-icon\">✅</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">").append(reachableCount).append("</div>")
                           .append("<div class=\"network-stat-label\">可达节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon warning\">")
                           .append("<i class=\"network-icon\">⚠️</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">").append(unreachableCount).append("</div>")
                           .append("<div class=\"network-stat-label\">不可达节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon info\">")
                           .append("<i class=\"network-icon\">🔗</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">").append(directConnectionCount).append("</div>")
                           .append("<div class=\"network-stat-label\">直连节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("</div>");
                
                // 生成详细卡片区域
                networksHtml.append("<div class=\"network-details-section\">")
                           .append("<h4>网络监控详情</h4>")
                           .append("<div class=\"network-cards\">");
                
                for (MonitoringResult network : networks) {
                    networksHtml.append(generateNetworkDetailCardHtml(network));
                }
                
                networksHtml.append("</div>")
                           .append("</div>");
            } else {
                networksHtml.append("<div class=\"network-overview-section\">")
                           .append("<h4>监控概览</h4>")
                           .append("<div class=\"network-overview-stats\">")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon\">")
                           .append("<i class=\"network-icon\">📡</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">0</div>")
                           .append("<div class=\"network-stat-label\">监控节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon success\">")
                           .append("<i class=\"network-icon\">✅</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">0</div>")
                           .append("<div class=\"network-stat-label\">可达节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon warning\">")
                           .append("<i class=\"network-icon\">⚠️</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">0</div>")
                           .append("<div class=\"network-stat-label\">不可达节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-stat-card\">")
                           .append("<div class=\"network-stat-icon info\">")
                           .append("<i class=\"network-icon\">🔗</i>")
                           .append("</div>")
                           .append("<div class=\"network-stat-content\">")
                           .append("<div class=\"network-stat-value\">0</div>")
                           .append("<div class=\"network-stat-label\">直连节点</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("</div>")
                           .append("<div class=\"network-details-section\">")
                           .append("<h4>网络监控详情</h4>")
                           .append("<p>暂无网络连通性监控数据</p>")
                           .append("</div>");
            }
            content = content.replace("<!-- NETWORKS_PLACEHOLDER -->", networksHtml.toString());
            
            // 生成结果表格HTML
            StringBuilder resultsTableHtml = new StringBuilder();
            for (MonitoringResult result : results) {
                // 获取状态的中文描述
                String statusText = getStatusText(result.getStatus());
                
                resultsTableHtml.append("<tr>")
                               .append("<td>").append(result.getName()).append("</td>")
                               .append("<td><div class=\"tag tag-").append(result.getStatus()).append("\">")
                               .append(statusText).append("</div></td>")
                               .append("<td>").append(formatTime(result.getMonitorTime())).append("</td>")
                               .append("<td>").append(result.getDetails()).append("</td>")
                               .append("</tr>");
            }
            content = content.replace("<!-- RESULTS_TABLE_PLACEHOLDER -->", resultsTableHtml.toString());
            
            // 写入文件 - 使用UTF-8编码避免Windows环境乱码
            try (OutputStreamWriter writer = new OutputStreamWriter(
                    new FileOutputStream(reportFile), StandardCharsets.UTF_8);
                 BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
                bufferedWriter.write(content);
            }
            
            // 在content内容中注入选项卡切换的JavaScript代码
            content = content.replace("</body>",
                    "<script>\n" +
                    "// 添加选项卡切换功能\n" +
                    "document.addEventListener('DOMContentLoaded', function() {\n" +
                    "    // 查找所有的tab-item\n" +
                    "    var tabItems = document.querySelectorAll('.tab-item');\n" +
                    "    var tabContents = document.querySelectorAll('.tab-content');\n" +
                    "    \n" +
                    "    // 默认情况下，第一个标签页是活跃的，所以我们将其他标签页内容隐藏\n" +
                    "    for(var i = 1; i < tabContents.length; i++) {\n" +
                    "        tabContents[i].style.display = 'none';\n" +
                    "    }\n" +
                    "    \n" +
                    "    // 为每个tab-item添加点击事件\n" +
                    "    tabItems.forEach(function(item, index) {\n" +
                    "        item.addEventListener('click', function() {\n" +
                    "            // 移除所有tab-item的active类\n" +
                    "            tabItems.forEach(function(tab) {\n" +
                    "                tab.classList.remove('active');\n" +
                    "            });\n" +
                    "            \n" +
                    "            // 隐藏所有的tab-content\n" +
                    "            tabContents.forEach(function(content) {\n" +
                    "                content.style.display = 'none';\n" +
                    "            });\n" +
                    "            \n" +
                    "            // 为当前点击的tab-item添加active类\n" +
                    "            this.classList.add('active');\n" +
                    "            \n" +
                    "            // 显示对应的tab-content\n" +
                    "            if(tabContents[index]) {\n" +
                    "                tabContents[index].style.display = 'block';\n" +
                    "            }\n" +
                    "        });\n" +
                    "    });\n" +
                    "    var systemTabItems = document.querySelectorAll('.system-tab-item');\n" +
                    "    var systemTabContents = document.querySelectorAll('.system-tab-content');\n" +
                    "    \n" +
                    "    // 默认情况下，第一个标签页是活跃的，所以我们将其他标签页内容隐藏\n" +
                    "    for(var i = 1; i < systemTabContents.length; i++) {\n" +
                    "        systemTabContents[i].style.display = 'none';\n" +
                    "    }\n" +
                    "    // 为每个system-tab-item添加点击事件\n" +
                    "    systemTabItems.forEach(function(item, index) {\n" +
                    "        item.addEventListener('click', function() {\n" +
                    "            // 移除所有tab-item的active类\n" +
                    "            systemTabItems.forEach(function(tab) {\n" +
                    "                tab.classList.remove('active');\n" +
                    "            });\n" +
                    "            \n" +
                    "            // 隐藏所有的tab-content\n" +
                    "            systemTabContents.forEach(function(content) {\n" +
                    "                content.style.display = 'none';\n" +
                    "            });\n" +
                    "            \n" +
                    "            // 为当前点击的tab-item添加active类\n" +
                    "            this.classList.add('active');\n" +
                    "            \n" +
                    "            // 显示对应的tab-content\n" +
                    "            if(systemTabContents[index]) {\n" +
                    "                systemTabContents[index].style.display = 'block';\n" +
                    "            }\n" +
                    "        });\n" +
                    "    });\n" +
                    "    \n" +
                    "    // 添加redis选项卡切换功能\n" +
                    "        // 查找所有的redis-tab-item\n" +
                    "        var redisTabItems = document.querySelectorAll('.redis-tab-item');\n" +
                    "        var redisTabContents = document.querySelectorAll('.redis-tab-content');\n" +
                    "        \n" +
                    "        // 默认情况下，第一个标签页是活跃的，所以我们将其他标签页内容隐藏\n" +
                    "        for(var i = 1; i < redisTabContents.length; i++) {\n" +
                    "            redisTabContents[i].style.display = 'none';\n" +
                    "        }\n" +
                    "        \n" +
                    "        // 为每个redis-tab-item添加点击事件\n" +
                    "        redisTabItems.forEach(function(item, index) {\n" +
                    "            item.addEventListener('click', function() {\n" +
                    "                // 移除所有redis-tab-item的active类\n" +
                    "                redisTabItems.forEach(function(tab) {\n" +
                    "                    tab.classList.remove('active');\n" +
                    "                });\n" +
                    "                \n" +
                    "                // 隐藏所有的redis-tab-content\n" +
                    "                redisTabContents.forEach(function(content) {\n" +
                    "                    content.style.display = 'none';\n" +
                    "                });\n" +
                    "                \n" +
                    "                // 为当前点击的redis-tab-item添加active类\n" +
                    "                this.classList.add('active');\n" +
                    "                \n" +
                    "                // 显示对应的redis-tab-content\n" +
                    "                if(redisTabContents[index]) {\n" +
                    "                    redisTabContents[index].style.display = 'block';\n" +
                    "                }\n" +
                    "            });\n" +
                    "        });\n" +
                    "    \n" +
                    "    // 添加mysql选项卡切换功能\n" +
                    "        // 查找所有的mysql-tab-item\n" +
                    "        var mysqlTabItems = document.querySelectorAll('.mysql-tab-item');\n" +
                    "        var mysqlTabContents = document.querySelectorAll('.mysql-tab-content');\n" +
                    "        \n" +
                    "        // 默认情况下，第一个标签页是活跃的，所以我们将其他标签页内容隐藏\n" +
                    "        for(var i = 1; i < mysqlTabContents.length; i++) {\n" +
                    "            mysqlTabContents[i].style.display = 'none';\n" +
                    "        }\n" +
                    "        \n" +
                    "        // 为每个mysql-tab-item添加点击事件\n" +
                    "        mysqlTabItems.forEach(function(item, index) {\n" +
                    "            item.addEventListener('click', function() {\n" +
                    "                // 移除所有mysql-tab-item的active类\n" +
                    "                mysqlTabItems.forEach(function(tab) {\n" +
                    "                    tab.classList.remove('active');\n" +
                    "                });\n" +
                    "                \n" +
                    "                // 隐藏所有的mysql-tab-content\n" +
                    "                mysqlTabContents.forEach(function(content) {\n" +
                    "                    content.style.display = 'none';\n" +
                    "                });\n" +
                    "                \n" +
                    "                // 为当前点击的mysql-tab-item添加active类\n" +
                    "                this.classList.add('active');\n" +
                    "                \n" +
                    "                // 显示对应的mysql-tab-content\n" +
                    "                if(mysqlTabContents[index]) {\n" + 
                    "                    mysqlTabContents[index].style.display = 'block';\n" +
                    "                }\n" +
                    "            });\n" +
                    "        });\n" +
                    "    \n" +
                    "    // 添加minio选项卡切换功能\n" +
                    "        // 查找所有的minio-tab-item\n" +
                    "        var minioTabItems = document.querySelectorAll('.minio-tab-item');\n" +
                    "        var minioTabContents = document.querySelectorAll('.minio-tab-content');\n" +
                    "        \n" +
                    "        // 默认情况下，第一个标签页是活跃的，所以我们将其他标签页内容隐藏\n" +
                    "        for(var i = 1; i < minioTabContents.length; i++) {\n" +
                    "            minioTabContents[i].style.display = 'none';\n" +
                    "        }\n" +
                    "        \n" +
                    "        // 为每个minio-tab-item添加点击事件\n" +
                    "        minioTabItems.forEach(function(item, index) {\n" +
                    "            item.addEventListener('click', function() {\n" +
                    "                // 移除所有minio-tab-item的active类\n" +
                    "                minioTabItems.forEach(function(tab) {\n" +
                    "                    tab.classList.remove('active');\n" +
                    "                });\n" +
                    "                \n" +
                    "                // 隐藏所有的minio-tab-content\n" +
                    "                minioTabContents.forEach(function(content) {\n" +
                    "                    content.style.display = 'none';\n" +
                    "                });\n" +
                    "                \n" +
                    "                // 为当前点击的minio-tab-item添加active类\n" +
                    "                this.classList.add('active');\n" +
                    "                \n" +
                    "                // 显示对应的minio-tab-content\n" +
                    "                if(minioTabContents[index]) {\n" +
                    "                    minioTabContents[index].style.display = 'block';\n" +
                    "                }\n" +
                    "            });\n" +
                    "        });\n" +
                    "    });\n" +
                    "</script>\n" +
                    "</body>");
                    
            // 重新写入添加了JavaScript的文件 - 使用UTF-8编码避免Windows环境乱码
            try (OutputStreamWriter writer = new OutputStreamWriter(
                    new FileOutputStream(reportFile), StandardCharsets.UTF_8);
                 BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
                bufferedWriter.write(content);
            }
            
            log.info("监控报告导出成功: {}", reportFile.getAbsolutePath());
            return reportFile.getAbsolutePath();
        } catch (Exception e) {
            log.error("导出监控报告失败", e);
            return null;
        }
    }
    
    /**
     * 生成JVM监控HTML
     */
    private String generateJvmMonitoringHtml(MonitoringResult jvmResult) {
        StringBuilder html = new StringBuilder();
        
        // 获取状态的中文描述
        String statusText = getStatusText(jvmResult.getStatus());
        
        // 添加状态信息
        html.append("<div class=\"row\">")
            .append("<div class=\"col-12\">")
            .append("<div class=\"tag tag-").append(jvmResult.getStatus()).append("\">")
            .append(statusText).append("</div>")
            .append("<p>").append(jvmResult.getDetails()).append("</p>")
            .append("<p>最后监控时间: ").append(formatTime(jvmResult.getMonitorTime())).append("</p>")
            .append("</div>")
            .append("</div>");
        
        // 只有在有指标数据时才添加选项卡
        if (jvmResult.getMetrics() != null && !jvmResult.getMetrics().isEmpty()) {
            html.append("<div class=\"tabs\">")
                .append("<div class=\"tab-nav\">")
                .append("<div class=\"tab-item active\">内存</div>")
                .append("<div class=\"tab-item\">线程</div>")
                .append("<div class=\"tab-item\">垃圾回收</div>")
                .append("<div class=\"tab-item\">系统信息</div>")
                .append("</div>");

            // 内存标签页内容 - 第一个标签
            html.append("<div class=\"tab-content\" style=\"display: block;\">")
                .append("<div class=\"row\">");
            
            // 堆内存
            html.append("<div class=\"col-6\">")
                .append("<h4>堆内存</h4>");
            
            Map<String, Object> heapMemory = (Map<String, Object>) jvmResult.getMetrics().get("heapMemory");
            if (heapMemory != null && heapMemory.get("usagePercent") != null) {
                String usagePercent = heapMemory.get("usagePercent").toString();
                double percentage = Double.parseDouble(usagePercent.replace("%", ""));
                String color = getMemoryColor(percentage);
                
                html.append("<div class=\"progress-bar\">")
                    .append("<div class=\"progress-bar-inner\" style=\"width: ").append(percentage).append("%; background-color: ").append(color).append(";\"></div>")
                    .append("</div>")
                    .append("<div style=\"text-align: center; margin-bottom: 10px;\">").append(usagePercent).append("</div>");
                
                html.append("<table class=\"metrics-table\">")
                    .append("<thead><tr><th>指标</th><th>值</th></tr></thead>")
                    .append("<tbody>");
                
                for (Map.Entry<String, Object> entry : heapMemory.entrySet()) {
                    if (!entry.getKey().equals("usagePercent")) {
                        html.append("<tr>")
                            .append("<td>").append(translateKey(entry.getKey())).append("</td>")
                            .append("<td>").append(entry.getValue()).append("</td>")
                            .append("</tr>");
                    }
                }
                
                html.append("</tbody>")
                    .append("</table>");
            } else {
                html.append("<div>暂无堆内存使用率数据</div>");
            }
            html.append("</div>");
            
            // 非堆内存
            html.append("<div class=\"col-6\">")
                .append("<h4>非堆内存 (元空间)</h4>");
            
            Map<String, Object> nonHeapMemory = (Map<String, Object>) jvmResult.getMetrics().get("nonHeapMemory");
            if (nonHeapMemory != null && nonHeapMemory.get("usagePercent") != null) {
                String usagePercent = nonHeapMemory.get("usagePercent").toString();
                double percentage = Double.parseDouble(usagePercent.replace("%", ""));
                String color = getMemoryColor(percentage);
                
                html.append("<div class=\"progress-bar\">")
                    .append("<div class=\"progress-bar-inner\" style=\"width: ").append(percentage).append("%; background-color: ").append(color).append(";\"></div>")
                    .append("</div>")
                    .append("<div style=\"text-align: center; margin-bottom: 10px;\">").append(usagePercent).append("</div>");
                
                html.append("<table class=\"metrics-table\">")
                    .append("<thead><tr><th>指标</th><th>值</th></tr></thead>")
                    .append("<tbody>");
                
                for (Map.Entry<String, Object> entry : nonHeapMemory.entrySet()) {
                    if (!entry.getKey().equals("usagePercent")) {
                        html.append("<tr>")
                            .append("<td>").append(translateKey(entry.getKey())).append("</td>")
                            .append("<td>").append(entry.getValue()).append("</td>")
                            .append("</tr>");
                    }
                }
                
                html.append("</tbody>")
                    .append("</table>");
            } else {
                html.append("<div>无法计算使用率 (无上限或数据不完整)</div>");
            }
            html.append("</div>")
                .append("</div>")
                .append("</div>");
            
            // 线程标签页内容 - 第二个标签
            html.append("<div class=\"tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            // 线程信息
            Map<String, Object> threadInfo = (Map<String, Object>) jvmResult.getMetrics().get("threadInfo");
            if (threadInfo != null && !threadInfo.isEmpty()) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>线程状态</h4>")
                    .append("<div class=\"thread-stats\">");
                
                // 当前线程数
                if (threadInfo.get("current") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value\">").append(threadInfo.get("current")).append("</div>")
                        .append("<div class=\"stat-label\">当前线程数</div>")
                        .append("</div>");
                }
                
                // 峰值线程数
                if (threadInfo.get("peak") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value\">").append(threadInfo.get("peak")).append("</div>")
                        .append("<div class=\"stat-label\">峰值线程数</div>")
                        .append("</div>");
                }
                
                // 守护线程数
                if (threadInfo.get("daemon") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value\">").append(threadInfo.get("daemon")).append("</div>")
                        .append("<div class=\"stat-label\">守护线程数</div>")
                        .append("</div>");
                }
                
                // 非守护线程数
                if (threadInfo.get("nonDaemon") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value\">").append(threadInfo.get("nonDaemon")).append("</div>")
                        .append("<div class=\"stat-label\">非守护线程数</div>")
                        .append("</div>");
                }
                
                // 启动线程总数
                if (threadInfo.get("totalStarted") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value\">").append(threadInfo.get("totalStarted")).append("</div>")
                        .append("<div class=\"stat-label\">启动线程总数</div>")
                        .append("</div>");
                }
                
                html.append("</div>")
                    .append("</div>");
                
                // 类加载信息
                Map<String, Object> classLoading = (Map<String, Object>) jvmResult.getMetrics().get("classLoading");
                if (classLoading != null && !classLoading.isEmpty()) {
                    html.append("<div class=\"col-12\">")
                        .append("<h4>类加载信息</h4>")
                        .append("<table class=\"metrics-table\">")
                        .append("<thead><tr><th>指标</th><th>值</th></tr></thead>")
                        .append("<tbody>");
                    
                    for (Map.Entry<String, Object> entry : classLoading.entrySet()) {
                        html.append("<tr>")
                            .append("<td>").append(translateKey(entry.getKey())).append("</td>")
                            .append("<td>").append(entry.getValue()).append("</td>")
                            .append("</tr>");
                    }
                    
                    html.append("</tbody>")
                        .append("</table>")
                        .append("</div>");
                }
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无线程信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            // 垃圾回收标签页内容 - 第三个标签
            html.append("<div class=\"tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> gcInfo = (Map<String, Object>) jvmResult.getMetrics().get("gc");
            if (gcInfo != null && !gcInfo.isEmpty()) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>垃圾回收统计</h4>");
                
                // 显示GC总计信息
                Map<String, Object> totalGcInfo = (Map<String, Object>) gcInfo.get("total");
                if (totalGcInfo != null) {
                    html.append("<div class=\"thread-stats\">");
                    
                    // 总收集次数
                    if (totalGcInfo.get("count") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value\">").append(totalGcInfo.get("count")).append("</div>")
                            .append("<div class=\"stat-label\">总收集次数</div>")
                            .append("</div>");
                    }
                    
                    // 总收集时间
                    if (totalGcInfo.get("time") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value\">").append(totalGcInfo.get("time")).append("</div>")
                            .append("<div class=\"stat-label\">总收集时间</div>")
                            .append("</div>");
                    }
                    
                    // 平均每次收集时间
                    if (totalGcInfo.get("avgTimePerGC") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value\">").append(totalGcInfo.get("avgTimePerGC")).append("</div>")
                            .append("<div class=\"stat-label\">平均每次收集时间</div>")
                            .append("</div>");
                    }
                    
                    html.append("</div>");
                }
                
                // 显示各GC收集器信息
                html.append("<h4>GC收集器详情</h4>")
                    .append("<table class=\"metrics-table\">")
                    .append("<thead><tr><th>收集器</th><th>收集次数</th><th>收集时间</th><th>平均时间</th><th>内存区域</th></tr></thead>")
                    .append("<tbody>");
                
                // 遍历各收集器
                for (Map.Entry<String, Object> entry : gcInfo.entrySet()) {
                    String collectorName = entry.getKey();
                    
                    // 跳过total，因为已经单独显示了
                    if (!"total".equals(collectorName) && !"error".equals(collectorName)) {
                        Map<String, Object> collectorInfo = (Map<String, Object>) entry.getValue();
                        html.append("<tr>")
                            .append("<td>").append(collectorName).append("</td>")
                            .append("<td>").append(collectorInfo.getOrDefault("count", "N/A")).append("</td>")
                            .append("<td>").append(collectorInfo.getOrDefault("time", "N/A")).append("</td>")
                            .append("<td>").append(collectorInfo.getOrDefault("avgTimePerGC", "N/A")).append("</td>")
                            .append("<td>").append(collectorInfo.getOrDefault("memoryPools", "N/A")).append("</td>")
                            .append("</tr>");
                    }
                }
                
                html.append("</tbody>")
                    .append("</table>");
                
                html.append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无垃圾回收信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            // 系统信息标签页内容 - 第四个标签
            html.append("<div class=\"tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> osInfo = (Map<String, Object>) jvmResult.getMetrics().get("os");
            if (osInfo != null && !osInfo.isEmpty()) {
                // 系统基本信息
                html.append("<div class=\"col-12\">")
                    .append("<h4>操作系统信息</h4>")
                    .append("<div class=\"system-info\">");
                
                // 操作系统名称
                if (osInfo.get("name") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">操作系统:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("name")).append(" ").append(osInfo.getOrDefault("version", "")).append("</div>")
                        .append("</div>");
                }
                
                // 系统架构
                if (osInfo.get("arch") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">系统架构:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("arch")).append("</div>")
                        .append("</div>");
                }
                
                // CPU核心数
                if (osInfo.get("availableProcessors") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">CPU核心数:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("availableProcessors")).append("</div>")
                        .append("</div>");
                }
                
                // 系统负载
                if (osInfo.get("systemLoadAverage") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">系统负载:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("systemLoadAverage")).append("</div>")
                        .append("</div>");
                }
                
                html.append("</div>");
                
                // JVM运行信息
                html.append("<h4>JVM运行信息</h4>")
                    .append("<div class=\"system-info\">");
                
                // JVM启动时间
                if (osInfo.get("jvmStartTime") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">启动时间:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("jvmStartTime")).append("</div>")
                        .append("</div>");
                }
                
                // JVM运行时长
                if (osInfo.get("jvmUptime") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">运行时长:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("jvmUptime")).append("</div>")
                        .append("</div>");
                }
                
                // CPU使用时间
                if (osInfo.get("processCpuTime") != null) {
                    html.append("<div class=\"system-info-item\">")
                        .append("<div class=\"system-info-label\">CPU使用时间:</div>")
                        .append("<div class=\"system-info-value\">").append(osInfo.get("processCpuTime")).append("</div>")
                        .append("</div>");
                }
                
                html.append("</div>");
                
                // 物理内存信息
                if (osInfo.get("totalPhysicalMemory") != null || osInfo.get("freePhysicalMemory") != null) {
                    html.append("<h4>物理内存信息</h4>")
                        .append("<div class=\"system-info\">");
                    
                    // 总物理内存
                    if (osInfo.get("totalPhysicalMemory") != null) {
                        html.append("<div class=\"system-info-item\">")
                            .append("<div class=\"system-info-label\">总物理内存:</div>")
                            .append("<div class=\"system-info-value\">").append(osInfo.get("totalPhysicalMemory")).append("</div>")
                            .append("</div>");
                    }
                    
                    // 可用物理内存
                    if (osInfo.get("freePhysicalMemory") != null) {
                        html.append("<div class=\"system-info-item\">")
                            .append("<div class=\"system-info-label\">可用物理内存:</div>")
                            .append("<div class=\"system-info-value\">").append(osInfo.get("freePhysicalMemory")).append("</div>")
                            .append("</div>");
                    }
                    
                    // 物理内存使用率
                    if (osInfo.get("physicalMemoryUsage") != null) {
                        html.append("<div class=\"system-info-item\">")
                            .append("<div class=\"system-info-label\">物理内存使用率:</div>")
                            .append("<div class=\"system-info-value\">").append(osInfo.get("physicalMemoryUsage")).append("</div>")
                            .append("</div>");
                    }
                    
                    html.append("</div>");
                }
                
                html.append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无系统信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            html.append("</div>");
        }
        
        return html.toString();
    }
    
    /**
     * 根据内存使用百分比获取颜色
     */
    private String getMemoryColor(double percentage) {
        if (percentage < 70) {
            return "#67c23a"; // 绿色，健康
        } else if (percentage < 85) {
            return "#e6a23c"; // 黄色，警告
        } else {
            return "#f56c6c"; // 红色，危险
        }
    }
    
    /**
     * 翻译JVM指标名称
     */
    private String translateKey(String key) {
        Map<String, String> translations = new HashMap<>();
        // 堆内存相关
        translations.put("init", "初始内存");
        translations.put("used", "已使用内存");
        translations.put("committed", "已提交内存");
        translations.put("max", "最大内存");
        translations.put("usagePercent", "内存使用率");
        translations.put("note", "备注");
        translations.put("error", "错误信息");
        
        // 线程相关
        translations.put("current", "当前线程数");
        translations.put("peak", "峰值线程数");
        translations.put("daemon", "守护线程数");
        translations.put("nonDaemon", "非守护线程数");
        translations.put("totalStarted", "启动线程总数");
        
        // 类加载相关
        translations.put("loaded", "当前已加载类数");
        translations.put("totalLoaded", "总加载类数");
        translations.put("unloaded", "已卸载类数");
        
        // GC相关
        translations.put("count", "收集次数");
        translations.put("time", "收集总时间");
        translations.put("avgTimePerGC", "平均每次收集时间");
        translations.put("memoryPools", "管理的内存区域");
        
        // 操作系统相关
        translations.put("name", "操作系统名称");
        translations.put("version", "操作系统版本");
        translations.put("arch", "系统架构");
        translations.put("availableProcessors", "CPU核心数");
        translations.put("systemLoadAverage", "系统负载平均值");
        translations.put("processCpuTime", "CPU使用时间");
        translations.put("totalPhysicalMemory", "系统物理内存总量");
        translations.put("freePhysicalMemory", "系统可用物理内存");
        translations.put("physicalMemoryUsage", "系统内存使用率");
        translations.put("jvmStartTime", "JVM启动时间");
        translations.put("jvmUptime", "JVM运行时长");
        
        return translations.getOrDefault(key, key);
    }
    
    /**
     * 格式化时间为字符串
     */
    private String formatTime(LocalDateTime time) {
        if (time == null) return "未知";
        return time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
    
    /**
     * 生成服务卡片HTML
     */
    private String generateServiceCardHtml(MonitoringResult service) {
        StringBuilder html = new StringBuilder();
        
        // 获取服务状态的中文描述
        String statusText;
        String statusClass;
        
        if (service.getStatus() == MonitoringStatus.NORMAL) {
            statusClass = "success";
            statusText = "健康";
        } else if (service.getStatus() == MonitoringStatus.UNKNOWN) {
            statusClass = "info";
            statusText = "未检测";
        } else {
            statusClass = "danger";
            statusText = "异常";
        }
        
        // 使用更现代的卡片样式
        html.append("<div class=\"service-card\" style=\"height: auto; margin-bottom: 15px;\">");
        html.append("<div class=\"service-header\">");
        html.append("<div class=\"service-name\">").append(service.getName()).append("</div>");
        html.append("<div class=\"tag tag-").append(statusClass).append("\">");
        html.append(statusText).append("</div>");
        html.append("</div>");
            
        // 表格式布局显示服务信息
        html.append("<table class=\"service-info-table\">");
        
        // 如果有URL信息，添加显示
        if (service.getMetrics() != null && service.getMetrics().get("url") != null) {
            html.append("<tr>");
            html.append("<td class=\"info-label\">服务地址:</td>");
            html.append("<td>").append(service.getMetrics().get("url")).append("</td>");
            html.append("</tr>");
        }
        
        // 添加请求方法
        if (service.getMetrics() != null && service.getMetrics().get("method") != null) {
            html.append("<tr>");
            html.append("<td class=\"info-label\">请求方法:</td>");
            html.append("<td>").append(service.getMetrics().get("method")).append("</td>");
            html.append("</tr>");
        }
        
        // 添加预期状态码
        if (service.getMetrics() != null && service.getMetrics().get("expectedRespCode") != null) {
            html.append("<tr>");
            html.append("<td class=\"info-label\">预期状态码:</td>");
            html.append("<td>").append(service.getMetrics().get("expectedRespCode")).append("</td>");
            html.append("</tr>");
        }
        
        // 如果有响应时间，添加显示
        if (service.getMetrics() != null && service.getMetrics().get("responseTime") != null) {
            String respTime = service.getMetrics().get("responseTime").toString();
            if (!"未记录".equals(respTime)) {
                html.append("<tr>");
                html.append("<td class=\"info-label\">响应时间:</td>");
                html.append("<td>").append(respTime).append("ms</td>");
                html.append("</tr>");
            }
        }
        
        // 状态详情
        html.append("<tr>");
        html.append("<td class=\"info-label\">状态详情:</td>");
        html.append("<td>").append(service.getDetails()).append("</td>");
        html.append("</tr>");
        
        // 最后监控时间
        String lastCheckTime = formatTime(service.getMonitorTime());
        if (service.getStatus() == MonitoringStatus.UNKNOWN) {
            lastCheckTime = "未检查";
        }
        html.append("<tr>");
        html.append("<td class=\"info-label\">最后监控时间:</td>");
        html.append("<td>").append(lastCheckTime).append("</td>");
        html.append("</tr>");
        
        html.append("</table>");
        html.append("</div>");
        return html.toString();
    }
    
    /**
     * 生成中间件卡片HTML
     */
    private String generateMiddlewareCardHtml(MonitoringResult middleware) {
        StringBuilder html = new StringBuilder();
        
        // 获取状态的中文描述
        String statusText = getStatusText(middleware.getStatus());
        
        html.append("<div class=\"service-card\" style=\"margin-bottom: 20px;\">")
            .append("<div class=\"service-header\">")
            .append("<div class=\"service-name\">").append(middleware.getName()).append("</div>")
            .append("<div class=\"tag tag-").append(middleware.getStatus()).append("\">")
            .append(statusText).append("</div>")
            .append("</div>")
            .append("<div class=\"metric-item\">")
            .append("<div class=\"metric-label\">状态详情:</div>")
            .append("<div class=\"metric-value\">").append(middleware.getDetails()).append("</div>")
            .append("</div>")
            .append("<div class=\"metric-item\">")
            .append("<div class=\"metric-label\">最后监控时间:</div>")
            .append("<div class=\"metric-value\">").append(formatTime(middleware.getMonitorTime())).append("</div>")
            .append("</div>");
        
        // 添加指标信息
        if (middleware.getMetrics() != null && !middleware.getMetrics().isEmpty()) {
            // Redis 特殊处理
            if ("Redis".equals(middleware.getName())) {
                html.append(generateRedisInfoHtml(middleware.getMetrics()));
            }
            // MySQL 特殊处理
            else if ("MySQL".equals(middleware.getName())) {
                html.append(generateMySQLInfoHtml(middleware.getMetrics()));
            }
            // MinIO 特殊处理
            else if ("MinIO".equals(middleware.getName())) {
                html.append(generateMinIOInfoHtml(middleware.getMetrics()));
            }
            // 通用指标展示
            else {
                html.append("<div class=\"expandable-content\">")
                    .append("<h3>监控指标</h3>")
                    .append("<table class=\"metrics-table\">")
                    .append("<thead><tr><th>指标名称</th><th>指标值</th></tr></thead>")
                    .append("<tbody>");
                
                middleware.getMetrics().forEach((key, value) -> {
                    String translatedKey = translateMiddlewareKey(key);
                    html.append("<tr>")
                        .append("<td>").append(translatedKey).append("</td>")
                        .append("<td>");
                    
                    if (value instanceof Map) {
                        html.append("<span class=\"metrics-nested\">");
                        ((Map<?, ?>) value).forEach((subKey, subValue) -> {
                            String translatedSubKey = translateMiddlewareKey(subKey.toString());
                            html.append("<div>")
                                .append("<span class=\"metrics-key\">").append(translatedSubKey).append("</span>: ")
                                .append("<span>").append(subValue).append("</span>")
                                .append("</div>");
                        });
                        html.append("</span>");
                    } else {
                        html.append("<span>").append(value).append("</span>");
                    }
                    
                    html.append("</td>")
                        .append("</tr>");
                });
                
                html.append("</tbody>")
                    .append("</table>")
                    .append("</div>");
            }
        }
        
        html.append("</div>");
        return html.toString();
    }
    
    /**
     * 生成Redis信息的HTML（参考JVM卡片展示形式）
     */
    private String generateRedisInfoHtml(Map<String, Object> metrics) {
        StringBuilder html = new StringBuilder();
        
        // 使用选项卡结构组织Redis信息
        html.append("<div class=\"redis-tabs\">")
            .append("<div class=\"redis-tab-nav\">")
            .append("<div class=\"redis-tab-item active\">基本信息</div>")
            .append("<div class=\"redis-tab-item\">内存使用</div>")
            .append("<div class=\"redis-tab-item\">性能指标</div>")
            .append("<div class=\"redis-tab-item\">连接信息</div>")
            .append("</div>");

        // 基本信息标签页内容 - 第一个标签
        html.append("<div class=\"redis-tab-content\" style=\"display: block;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> basic = (Map<String, Object>) metrics.getOrDefault("basic", new HashMap<>());
        
        if (!basic.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>Redis基本信息</h4>")
                .append("<div class=\"system-info\">");
            
            // Redis版本
            if (basic.get("version") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">Redis版本:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("version")).append("</div>")
                    .append("</div>");
            }
            
            // 运行模式
            if (basic.get("mode") != null) {
                String mode = basic.get("mode").toString();
                String modeText = "standalone".equals(mode) ? "单机模式" : 
                                 "cluster".equals(mode) ? "集群模式" : 
                                 "sentinel".equals(mode) ? "哨兵模式" : mode;
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">运行模式:</div>")
                    .append("<div class=\"system-info-value\">").append(modeText).append("</div>")
                    .append("</div>");
            }
            
            // 运行时长
            if (basic.get("uptime") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">运行时长:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("uptime")).append("</div>")
                    .append("</div>");
            }
            
            // 操作系统
            if (basic.get("os") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">操作系统:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("os")).append("</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无基本信息数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        // 内存使用标签页内容 - 第二个标签
        html.append("<div class=\"redis-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> memory = (Map<String, Object>) metrics.getOrDefault("memory", new HashMap<>());
        
        if (!memory.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>内存使用情况</h4>");
            
            // 内存使用率进度条
            if (memory.get("usagePercent") != null && !"N/A".equals(memory.get("usagePercent").toString())) {
                String usagePercent = memory.get("usagePercent").toString();
                double percentage = Double.parseDouble(usagePercent.replace("%", ""));
                String color = getMemoryColor(percentage);
                
                html.append("<div class=\"progress-bar\">")
                    .append("<div class=\"progress-bar-inner\" style=\"width: ").append(percentage).append("%; background-color: ").append(color).append(";\"></div>")
                    .append("</div>")
                    .append("<div style=\"text-align: center; margin-bottom: 15px;\">").append(usagePercent).append("</div>");
            }
            
            // 内存统计卡片
            html.append("<div class=\"thread-stats\">");
            
            // 已用内存
            if (memory.get("usedMemory") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(memory.get("usedMemory")).append("</div>")
                    .append("<div class=\"stat-label\">已用内存</div>")
                    .append("</div>");
            }
            
            // 最大内存
            if (memory.get("maxMemory") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(memory.get("maxMemory")).append("</div>")
                    .append("<div class=\"stat-label\">最大内存</div>")
                    .append("</div>");
            }
            
            // 物理内存
            if (memory.get("usedMemoryRss") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(memory.get("usedMemoryRss")).append("</div>")
                    .append("<div class=\"stat-label\">物理内存</div>")
                    .append("</div>");
            }
            
            // 内存碎片率
            if (memory.get("memFragmentationRatio") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(memory.get("memFragmentationRatio")).append("</div>")
                    .append("<div class=\"stat-label\">内存碎片率</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无内存使用数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        // 性能指标标签页内容 - 第三个标签
        html.append("<div class=\"redis-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> performance = (Map<String, Object>) metrics.getOrDefault("performance", new HashMap<>());
        
        if (!performance.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>Redis性能指标</h4>")
                .append("<div class=\"thread-stats\">");
            
            // 每秒操作数
            if (performance.get("opsPerSecond") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("opsPerSecond")).append("</div>")
                    .append("<div class=\"stat-label\">每秒操作数</div>")
                    .append("</div>");
            }
            
            // 命中率
            if (performance.get("hitRatio") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("hitRatio")).append("</div>")
                    .append("<div class=\"stat-label\">缓存命中率</div>")
                    .append("</div>");
            }
            
            // 命令总数
            if (performance.get("totalCommands") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("totalCommands")).append("</div>")
                    .append("<div class=\"stat-label\">命令总数</div>")
                    .append("</div>");
            }
            
            html.append("</div>");
            
            // 详细性能表格
            html.append("<h4>性能详情</h4>")
                .append("<table class=\"metrics-table\">")
                .append("<thead><tr><th>指标</th><th>值</th></tr></thead>")
                .append("<tbody>");
            
            // 键查询命中
            if (performance.get("keyspaceHits") != null) {
                html.append("<tr>")
                    .append("<td>键查询命中次数</td>")
                    .append("<td>").append(performance.get("keyspaceHits")).append("</td>")
                    .append("</tr>");
            }
            
            // 键查询未命中
            if (performance.get("keyspaceMisses") != null) {
                html.append("<tr>")
                    .append("<td>键查询未命中次数</td>")
                    .append("<td>").append(performance.get("keyspaceMisses")).append("</td>")
                    .append("</tr>");
            }
            
            html.append("</tbody>")
                .append("</table>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无性能指标数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        // 连接信息标签页内容 - 第四个标签
        html.append("<div class=\"redis-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> connection = (Map<String, Object>) metrics.getOrDefault("connection", new HashMap<>());
        
        if (!connection.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>Redis连接信息</h4>")
                .append("<div class=\"thread-stats\">");
            
            // 当前连接数
            if (connection.get("connectedClients") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("connectedClients")).append("</div>")
                    .append("<div class=\"stat-label\">当前连接数</div>")
                    .append("</div>");
            }
            
            // 阻塞连接数
            if (connection.get("blockedClients") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("blockedClients")).append("</div>")
                    .append("<div class=\"stat-label\">阻塞连接数</div>")
                    .append("</div>");
            }
            
            // 最大连接数
            if (connection.get("maxClients") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("maxClients")).append("</div>")
                    .append("<div class=\"stat-label\">最大连接数</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无连接信息数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        html.append("</div>");
        
        return html.toString();
    }
    
    /**
     * 生成MySQL信息的HTML
     */
    private String generateMySQLInfoHtml(Map<String, Object> metrics) {
        StringBuilder html = new StringBuilder();
        
        // 使用选项卡结构组织MySQL信息
        html.append("<div class=\"mysql-tabs\">")
            .append("<div class=\"mysql-tab-nav\">")
            .append("<div class=\"mysql-tab-item active\">基本信息</div>")
            .append("<div class=\"mysql-tab-item\">连接信息</div>")
            .append("<div class=\"mysql-tab-item\">性能指标</div>")
            .append("<div class=\"mysql-tab-item\">InnoDB引擎</div>")
            .append("</div>");

        // 基本信息标签页内容 - 第一个标签
        html.append("<div class=\"mysql-tab-content\" style=\"display: block;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> basic = (Map<String, Object>) metrics.getOrDefault("basic", new HashMap<>());
        
        if (!basic.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>MySQL基本信息</h4>")
                .append("<div class=\"system-info\">");
            
            // MySQL版本
            if (basic.get("version") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">MySQL版本:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("version")).append("</div>")
                    .append("</div>");
            }
            
            // 当前数据库
            if (basic.get("database") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">当前数据库:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("database")).append("</div>")
                    .append("</div>");
            }
            
            // 默认字符集
            if (basic.get("characterSet") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">默认字符集:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("characterSet")).append("</div>")
                    .append("</div>");
            }
            
            // 排序规则
            if (basic.get("collation") != null) {
                html.append("<div class=\"system-info-item\">")
                    .append("<div class=\"system-info-label\">排序规则:</div>")
                    .append("<div class=\"system-info-value\">").append(basic.get("collation")).append("</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无基本信息数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        // 连接信息标签页内容 - 第二个标签
        html.append("<div class=\"mysql-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> connection = (Map<String, Object>) metrics.getOrDefault("connection", new HashMap<>());
        
        if (!connection.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>MySQL连接信息</h4>")
                .append("<div class=\"thread-stats\">");
            
            // 最大连接数
            if (connection.get("maxConnections") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("maxConnections")).append("</div>")
                    .append("<div class=\"stat-label\">最大连接数</div>")
                    .append("</div>");
            }
            
            // 已连接线程数
            if (connection.get("threadsConnected") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("threadsConnected")).append("</div>")
                    .append("<div class=\"stat-label\">已连接线程数</div>")
                    .append("</div>");
            }
            
            // 运行中线程数
            if (connection.get("threadsRunning") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("threadsRunning")).append("</div>")
                    .append("<div class=\"stat-label\">运行中线程数</div>")
                    .append("</div>");
            }
            
            // 已缓存线程数
            if (connection.get("threadsCached") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(connection.get("threadsCached")).append("</div>")
                    .append("<div class=\"stat-label\">已缓存线程数</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无连接信息数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        // 性能指标标签页内容 - 第三个标签
        html.append("<div class=\"mysql-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> performance = (Map<String, Object>) metrics.getOrDefault("performance", new HashMap<>());
        
        if (!performance.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>MySQL性能指标</h4>")
                .append("<div class=\"thread-stats\">");
            
            // 每秒查询数
            if (performance.get("queriesPerSecond") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("queriesPerSecond")).append("</div>")
                    .append("<div class=\"stat-label\">每秒查询数</div>")
                    .append("</div>");
            }
            
            // 慢查询数
            if (performance.get("slowQueries") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("slowQueries")).append("</div>")
                    .append("<div class=\"stat-label\">慢查询数</div>")
                    .append("</div>");
            }
            
            // 每秒SELECT
            if (performance.get("selectsPerSecond") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("selectsPerSecond")).append("</div>")
                    .append("<div class=\"stat-label\">每秒SELECT</div>")
                    .append("</div>");
            }
            
            // 每秒INSERT
            if (performance.get("insertsPerSecond") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(performance.get("insertsPerSecond")).append("</div>")
                    .append("<div class=\"stat-label\">每秒INSERT</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无性能指标数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        // InnoDB引擎标签页内容 - 第四个标签
        html.append("<div class=\"mysql-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">");
        
        Map<String, Object> innodb = (Map<String, Object>) metrics.getOrDefault("innodb", new HashMap<>());
        
        if (!innodb.isEmpty()) {
            html.append("<div class=\"col-12\">")
                .append("<h4>InnoDB引擎指标</h4>")
                .append("<div class=\"thread-stats\">");
            
            // 缓冲池使用率
            if (innodb.get("bufferPoolUtilization") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(innodb.get("bufferPoolUtilization")).append("</div>")
                    .append("<div class=\"stat-label\">缓冲池使用率</div>")
                    .append("</div>");
            }
            
            // 缓冲池命中率
            if (innodb.get("bufferPoolHitRate") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(innodb.get("bufferPoolHitRate")).append("</div>")
                    .append("<div class=\"stat-label\">缓冲池命中率</div>")
                    .append("</div>");
            }
            
            // 读取行数
            if (innodb.get("rowsRead") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(innodb.get("rowsRead")).append("</div>")
                    .append("<div class=\"stat-label\">读取行数</div>")
                    .append("</div>");
            }
            
            // 插入行数
            if (innodb.get("rowsInserted") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(innodb.get("rowsInserted")).append("</div>")
                    .append("<div class=\"stat-label\">插入行数</div>")
                    .append("</div>");
            }
            
            // 更新行数
            if (innodb.get("rowsUpdated") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(innodb.get("rowsUpdated")).append("</div>")
                    .append("<div class=\"stat-label\">更新行数</div>")
                    .append("</div>");
            }
            
            // 删除行数
            if (innodb.get("rowsDeleted") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(innodb.get("rowsDeleted")).append("</div>")
                    .append("<div class=\"stat-label\">删除行数</div>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
        } else {
            html.append("<div class=\"col-12\">")
                .append("<p>暂无InnoDB引擎数据</p>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>");
        
        html.append("</div>");
        
        return html.toString();
    }
    
    /**
     * 翻译中间件指标名称
     */
    private String translateMiddlewareKey(String key) {
        Map<String, String> translations = new HashMap<>();
        // 通用
        translations.put("version", "版本");
        translations.put("database", "数据库");
        translations.put("endpoint", "服务端点");
        translations.put("clusterName", "集群名称");
        translations.put("status", "状态");
        translations.put("numberOfNodes", "节点数量");
        translations.put("numberOfDataNodes", "数据节点数量");
        translations.put("activeShards", "活跃分片数");
        
        // Elasticsearch特定
        translations.put("GREEN", "健康");
        translations.put("YELLOW", "警告");
        translations.put("RED", "危险");
        
        // MinIO特定
        translations.put("testBucketExists", "测试桶存在");
        translations.put("buckets", "存储桶");
        translations.put("name", "名称");
        translations.put("creationDate", "创建时间");
        
        return translations.getOrDefault(key, key);
    }
    
    /**
     * 生成网络详细卡片HTML
     */
    private String generateNetworkDetailCardHtml(MonitoringResult network) {
        StringBuilder html = new StringBuilder();
        String networkName = network.getName().replace("Network_", "");
        
        // 获取状态的中文描述
        String statusText = getStatusText(network.getStatus());
        String statusType = network.getStatus().toString().toLowerCase();
        
        html.append("<div class=\"network-detail-card\">")
            .append("<div class=\"network-card-header\">")
            .append("<div class=\"network-card-title\">")
            .append("<div class=\"network-node-name\">").append(networkName).append("</div>");
        
        // 添加标签
        html.append("<div class=\"network-tags\">");
        
        if (network.getMetrics() != null) {
            // 连接类型标签
            if (network.getMetrics().get("connectionType") != null) {
                String connectionType = network.getMetrics().get("connectionType").toString();
                String tagClass = "direct".equals(connectionType) ? "direct" : "indirect";
                String tagText = "direct".equals(connectionType) ? "直连" : "间接";
                
                html.append("<div class=\"network-tag ").append(tagClass).append("\">")
                    .append(tagText).append("</div>");
            }
            
            // 标签信息
            if (network.getMetrics().get("label") != null) {
                html.append("<div class=\"network-tag\">")
                    .append(network.getMetrics().get("label"))
                    .append("</div>");
            }
        }
        
        html.append("</div>") // 结束network-tags
            .append("</div>") // 结束network-card-title
            .append("<div class=\"network-status-badge\">")
            .append("<div class=\"tag tag-").append(statusType).append("\">")
            .append(statusText).append("</div>")
            .append("</div>")
            .append("</div>"); // 结束network-card-header
        
        // 卡片内容
        html.append("<div class=\"network-card-content\">");
        
        // 基本信息区域
        html.append("<div class=\"network-info-section\">");
        
        if (network.getMetrics() != null) {
            // 目标地址
            html.append("<div class=\"network-info-item\">")
                .append("<span class=\"network-info-label\">目标地址:</span>")
                .append("<span class=\"network-info-value\">").append(network.getMetrics().get("host")).append("</span>")
                .append("</div>");
            
            // 端口
            if (network.getMetrics().get("port") != null) {
                html.append("<div class=\"network-info-item\">")
                    .append("<span class=\"network-info-label\">端口:</span>")
                    .append("<span class=\"network-info-value\">").append(network.getMetrics().get("port")).append("</span>")
                    .append("</div>");
            }
            
            // 服务类型
            if (network.getMetrics().get("type") != null) {
                html.append("<div class=\"network-info-item\">")
                    .append("<span class=\"network-info-label\">服务类型:</span>")
                    .append("<span class=\"network-info-value\">").append(network.getMetrics().get("type")).append("</span>")
                    .append("</div>");
            }
        }
        
        // 检查时间
        html.append("<div class=\"network-info-item\">")
            .append("<span class=\"network-info-label\">检查时间:</span>")
            .append("<span class=\"network-info-value\">").append(formatTime(network.getMonitorTime())).append("</span>")
            .append("</div>");
        
        html.append("</div>"); // 结束network-info-section
        
        // 测试结果区域
        if (network.getMetrics() != null) {
            html.append("<div class=\"network-test-results\">");
            
            // 主机可达性测试
            html.append("<div class=\"network-test-item\">")
                .append("<div class=\"network-test-label\">")
                .append("<i class=\"el-icon-location\"></i>")
                .append("主机可达性")
                .append("</div>")
                .append("<div class=\"network-test-result");
            
            boolean isReachable = network.getMetrics().get("isReachable") != null && 
                                 Boolean.TRUE.equals(network.getMetrics().get("isReachable"));
            html.append(isReachable ? " success" : " error");
            html.append("\">")
                .append("<i class=\"").append(isReachable ? "el-icon-success" : "el-icon-error").append("\"></i>")
                .append("<span>").append(isReachable ? "可达" : "不可达").append("</span>")
                .append("</div>")
                .append("</div>");
            
            // 端口连接测试
            if (network.getMetrics().get("port") != null) {
                html.append("<div class=\"network-test-item\">")
                    .append("<div class=\"network-test-label\">")
                    .append("<i class=\"el-icon-connection\"></i>")
                    .append("端口连接")
                    .append("</div>")
                    .append("<div class=\"network-test-result");
                
                boolean isPortOpen = network.getMetrics().get("isPortOpen") != null && 
                                   Boolean.TRUE.equals(network.getMetrics().get("isPortOpen"));
                html.append(isPortOpen ? " success" : " error");
                html.append("\">")
                    .append("<i class=\"").append(isPortOpen ? "el-icon-success" : "el-icon-error").append("\"></i>")
                    .append("<span>").append(isPortOpen ? "开放" : "关闭").append("</span>")
                    .append("</div>")
                    .append("</div>");
            }
            
            // 响应时间
            if (network.getMetrics().get("responseTime") != null) {
                html.append("<div class=\"network-test-item\">")
                    .append("<div class=\"network-test-label\">")
                    .append("<i class=\"el-icon-time\"></i>")
                    .append("响应时间")
                    .append("</div>")
                    .append("<div class=\"network-test-result\">")
                    .append("<span class=\"response-time");
                
                // 根据响应时间设置颜色
                try {
                    int responseTime = Integer.parseInt(network.getMetrics().get("responseTime").toString());
                    if (responseTime < 100) {
                        html.append(" success");
                    } else if (responseTime < 200) {
                        html.append(" warning");
                    } else {
                        html.append(" danger");
                    }
                } catch (NumberFormatException e) {
                    // 如果解析失败，使用默认样式
                }
                
                html.append("\">")
                    .append(network.getMetrics().get("responseTime")).append("ms")
                    .append("</span>")
                    .append("</div>")
                    .append("</div>");
            }
            
            html.append("</div>"); // 结束network-test-results
        }
        
        // 详细信息文本
        if (network.getDetails() != null && !network.getDetails().isEmpty()) {
            html.append("<div class=\"network-details-text\">")
                .append("<p>").append(network.getDetails()).append("</p>")
                .append("</div>");
        }
        
        html.append("</div>") // 结束network-card-content
            .append("</div>"); // 结束network-detail-card
        
        return html.toString();
    }
    
    /**
     * 获取系统信息
     */
    private Map<String, String> getSystemInfo() {
        Map<String, String> info = new HashMap<>();
        info.put("osName", System.getProperty("os.name"));
        info.put("osVersion", System.getProperty("os.version"));
        info.put("javaVersion", System.getProperty("java.version"));
        info.put("hostName", getHostName());
        info.put("ip", getHostAddress());
        return info;
    }
    
    /**
     * 获取主机名
     */
    private String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            log.warn("获取主机名失败", e);
            return "未知主机";
        }
    }
    
    /**
     * 获取主机IP地址
     */
    private String getHostAddress() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            log.warn("获取主机IP失败", e);
            return "未知IP";
        }
    }
    
    /**
     * 对监控结果进行分类
     */
    private Map<String, List<MonitoringResult>> categorizeResults(List<MonitoringResult> results) {
        Map<String, List<MonitoringResult>> categorized = new HashMap<>();
        
        List<MonitoringResult> coreServices = new ArrayList<>();
        List<MonitoringResult> middlewares = new ArrayList<>();
        List<MonitoringResult> networks = new ArrayList<>();
        
        // 先查找所有目标服务配置，用于为核心服务添加URL信息
        List<MonitoringProperties.TargetService> targetServices = properties.getTargetService();
        Map<String, MonitoringProperties.TargetService> targetServiceMap = new HashMap<>();
        
        if (targetServices != null) {
            for (MonitoringProperties.TargetService service : targetServices) {
                targetServiceMap.put(service.getName(), service);
            }
        }
        
        // 检查每个监控结果，按类型分类
        for (MonitoringResult result : results) {
            if (result.getName().startsWith("Network_")) {
                networks.add(result);
            } else if (result.getName().equals("JVM") || 
                       result.getName().equals("Redis") || 
                       result.getName().equals("MySQL") || 
                       result.getName().equals("Elasticsearch") || 
                       result.getName().equals("MinIO") ||
                       result.getName().equals("System")) {
                middlewares.add(result);
            } else {
                // 直接添加核心服务结果，保留原始监控数据
                coreServices.add(result);
            }
        }
        
        // 如果核心服务为空但targetServiceMap不为空，从targetServiceMap中创建占位结果
        if (coreServices.isEmpty() && !targetServiceMap.isEmpty()) {
            log.info("未检测到核心服务状态，从配置中创建占位信息");
            
            for (Map.Entry<String, MonitoringProperties.TargetService> entry : targetServiceMap.entrySet()) {
                MonitoringProperties.TargetService service = entry.getValue();
                
                Map<String, Object> metrics = new HashMap<>();
                metrics.put("url", service.getUrl());
                metrics.put("responseTime", "未记录");
                
                // 添加请求方法和预期状态码信息
                String method = service.getMethod();
                if (method == null) {
                    method = "GET"; // 默认为GET方法
                }
                metrics.put("method", method);
                
                // 添加预期状态码
                Integer expectedRespCode = service.getExpectedRespCode();
                if (expectedRespCode == null) {
                    expectedRespCode = 200; // 默认为200
                }
                metrics.put("expectedRespCode", expectedRespCode);
                
                MonitoringResult placeholder = MonitoringResult.builder()
                        .name(service.getName())
                        .status(MonitoringStatus.UNKNOWN)
                        .monitorTime(LocalDateTime.now())
                        .details("服务状态未检测")
                        .metrics(metrics)
                        .build();
                
                coreServices.add(placeholder);
            }
        }
        
        categorized.put("coreServices", coreServices);
        categorized.put("middlewares", middlewares);
        categorized.put("networks", networks);
        
        return categorized;
    }
    
    @Override
    public Map<String, Boolean> getMiddlewareConfigStatus() {
        Map<String, Boolean> status = new HashMap<>();
        
        log.debug("检查中间件配置状态");
        log.debug("Middleware对象: {}", properties.getMiddleware());
        
        // 确保middleware对象已初始化
        ensureMiddlewareInitialized();
        
        // 检查JVM配置
        boolean jvmEnabled = properties.getMiddleware().getJvm() != null && properties.getMiddleware().getJvm().isEnabled();
        status.put("JVM", jvmEnabled);
        log.debug("JVM配置状态: {}", jvmEnabled);
        
        // 检查Redis配置
        boolean redisEnabled = properties.getMiddleware().getRedis() != null && 
                              properties.getMiddleware().getRedis().isEnabled() && 
                              redisConnectionFactory != null;
        status.put("Redis", redisEnabled);
        log.debug("Redis配置状态: {}", redisEnabled);
        
        // 检查Elasticsearch配置
        boolean esEnabled = properties.getMiddleware().getElasticsearch() != null && 
                           properties.getMiddleware().getElasticsearch().isEnabled() && 
                           elasticsearchClient != null;
        status.put("Elasticsearch", esEnabled);
        log.debug("Elasticsearch配置状态: {}", esEnabled);
        
        // 检查MySQL配置
        boolean mysqlEnabled = properties.getMiddleware().getMysql() != null && 
                              properties.getMiddleware().getMysql().isEnabled();
        status.put("MySQL", mysqlEnabled);
        log.debug("MySQL配置状态: {}", mysqlEnabled);
        
        // 检查MinIO配置
        boolean minioEnabled = properties.getMiddleware().getMinio() != null && 
                              properties.getMiddleware().getMinio().isEnabled();
        status.put("MinIO", minioEnabled);
        log.debug("MinIO配置对象: {}", properties.getMiddleware().getMinio());
        log.debug("MinIO配置状态: {}", minioEnabled);
        
        // System监控始终启用，因为它不需要外部依赖
        status.put("System", true);
        log.debug("System配置状态: true (始终启用)");
        
        log.debug("所有中间件配置状态: {}", status);
        return status;
    }
    
    /**
     * 确保middleware对象已初始化
     */
    private void ensureMiddlewareInitialized() {
        if (properties.getMiddleware() == null) {
            log.warn("Middleware配置对象为null，正在初始化");
            properties.setMiddleware(new MonitoringProperties.Middleware());
        }
        
        // 确保所有中间件配置对象都已初始化
        if (properties.getMiddleware().getJvm() == null) {
            log.debug("初始化JVM配置对象");
            properties.getMiddleware().setJvm(new MonitoringProperties.Middleware.Jvm());
        }
        if (properties.getMiddleware().getRedis() == null) {
            log.debug("初始化Redis配置对象");
            properties.getMiddleware().setRedis(new MonitoringProperties.Middleware.Redis());
        }
        if (properties.getMiddleware().getElasticsearch() == null) {
            log.debug("初始化Elasticsearch配置对象");
            properties.getMiddleware().setElasticsearch(new MonitoringProperties.Middleware.Elasticsearch());
        }
        if (properties.getMiddleware().getMysql() == null) {
            log.debug("初始化MySQL配置对象");
            properties.getMiddleware().setMysql(new MonitoringProperties.Middleware.MySQL());
        }
        if (properties.getMiddleware().getMinio() == null) {
            log.debug("初始化MinIO配置对象");
            properties.getMiddleware().setMinio(new MonitoringProperties.Middleware.MinIO());
        }
    }
    
    // 辅助方法：构建禁用状态的监控结果
    private MonitoringResult buildDisabledResult(String name) {
        return MonitoringResult.builder()
                .name(name)
                .status(MonitoringStatus.UNKNOWN)
                .monitorTime(LocalDateTime.now())
                .details(name + " 监控未启用")
                .build();
    }
    
    // 辅助方法：检查主机是否可达，兼容Windows和Linux
    private boolean pingHost(String host) {
        try {
            // 检测操作系统类型
            boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
            String pingCommand;
            
            if (isWindows) {
                // Windows下的Ping命令
                pingCommand = "ping -n 1 -w 3000 " + host;
            } else {
                // Linux/Mac下的Ping命令
                pingCommand = "ping -c 1 -W 3 " + host;
            }
            
            log.debug("执行Ping命令: {}", pingCommand);
            Process process = Runtime.getRuntime().exec(pingCommand);
            int returnValue = process.waitFor();
            return returnValue == 0;
        } catch (Exception e) {
            log.error("Ping主机失败: {}", host, e);
            return false;
        }
    }
    
    // 辅助方法：检查端口是否开放
    private static boolean isPortOpen(String host, int port) {
        if (port <= 0) {
            return false;
        }
        
        try (Socket socket = new Socket()) {
            // 设置连接超时时间为3秒
            socket.connect(new InetSocketAddress(host, port), 3000);
            
            // 如果能建立连接，尝试进一步验证是否有服务响应
            // 对于HTTP和HTTPS服务，尝试发送简单请求
            if (port == 80 || port == 8080 || port == 443 || port == 8443 || port == 9080 || port == 9443) {
                try {
                    // 设置不同的请求头，取决于是HTTP还是HTTPS
                    boolean isHttps = (port == 443 || port == 8443 || port == 9443);
                    String protocol = isHttps ? "HTTPS" : "HTTP";
                    
                    // 发送最基本的HTTP请求头
                    OutputStream out = socket.getOutputStream();
                    String request = "HEAD / " + protocol + "/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n";
                    out.write(request.getBytes(StandardCharsets.UTF_8));
                    out.flush();
                    
                    // 读取响应
                    InputStream in = socket.getInputStream();
                    byte[] buffer = new byte[1024];
                    int bytesRead = in.read(buffer);
                    
                    // 检查是否有响应数据
                    if (bytesRead > 0) {
                        // 转换为字符串以检查响应头
                        String response = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                        // 检查是否包含HTTP状态行
                        return response.startsWith("HTTP/") || response.contains("200 OK");
                    }
                    
                    return false; // 没有响应数据
                } catch (Exception e) {
                    log.debug("HTTP服务验证失败: {} - {}", host, port, e);
                    // 连接已建立但无法获取有效响应，可能是非HTTP服务或HTTP服务异常
                    return false;
                }
            }
            
            // 对于数据库等特定服务，可以添加更多的验证逻辑
            // 例如，MySQL(3306), PostgreSQL(5432), Redis(6379)等
            
            // 对于非HTTP服务，仅连接成功就视为服务在运行
            // 但为了更准确的验证，可以添加更多特定端口的验证逻辑
            return true;
        } catch (Exception e) {
            log.debug("端口连接失败: {} - {}", host, port, e);
            return false;
        }
    }
    
    // 辅助方法：检查端口是否被有效服务占用（支持本地和远程服务）
    private static boolean isPortInUse(String host, int port) {
        if (port <= 0) {
            return false;
        }
        
        // 检查是否为本地地址
        boolean isLocalhost = "localhost".equals(host) || "127.0.0.1".equals(host) || 
                              host.equals(getLocalHostAddress());
        
        if (isLocalhost) {
            // 本地服务检查
            return checkLocalPortInUse(port);
        } else {
            // 远程服务检查
            return checkRemotePortInUse(host, port);
        }
    }
    
    // 获取本机地址
    private static String getLocalHostAddress() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            log.error("获取本机地址失败", e);
            return "";
        }
    }
    
    // 检查本地端口是否被占用
    private static boolean checkLocalPortInUse(int port) {
        // 检查操作系统类型
        boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
        
        try {
            if (isWindows) {
                // Windows下使用netstat命令
                Process process = Runtime.getRuntime().exec("netstat -ano | findstr " + port);
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("LISTENING") && line.contains(":" + port)) {
                        return true;
                    }
                }
            } else {
                // Linux/Mac下使用lsof命令
                Process process = Runtime.getRuntime().exec("lsof -i:" + port);
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                return reader.readLine() != null; // 如果有输出则表示端口被占用
            }
            return false;
        } catch (Exception e) {
            log.error("检查本地端口占用失败: {}", port, e);
            // 如果执行命令失败，默认使用Socket方式检查
            try {
                // 尝试连接本地端口，如果能连接上，说明端口被占用
                Socket socket = new Socket();
                socket.connect(new InetSocketAddress("localhost", port), 500);
                socket.close();
                return true; // 能连接说明端口被占用
            } catch (IOException ex) {
                // 连接失败，可能端口未被占用，或者端口被占用但服务不接受连接
                return false;
            }
        }
    }
    
    // 检查远程端口是否有服务运行
    private static boolean checkRemotePortInUse(String host, int port) {
        try (Socket socket = new Socket()) {
            // 尝试连接远程端口
            socket.connect(new InetSocketAddress(host, port), 3000);
            
            // 根据不同服务类型进行特定验证
            if (isHttpPort(port)) {
                // 对HTTP/HTTPS端口进行特定验证
                return verifyHttpService(socket, host, port);
            } else if (port == 3306) {
                // MySQL端口验证
                return verifyMySQLService(socket);
            } else if (port == 6379) {
                // Redis端口验证
                return verifyRedisService(socket);
            } else if (port == 27017) {
                // MongoDB端口验证
                return verifyMongoDBService(socket);
            } else {
                // 对于其他端口类型，只要能连接就认为服务在运行
                return true;
            }
        } catch (Exception e) {
            log.debug("远程端口连接失败: {} - {}", host, port, e);
            return false;
        }
    }
    
    // 判断是否为HTTP端口
    private static boolean isHttpPort(int port) {
        return port == 80 || port == 8080 || port == 443 || port == 8443 || 
               port == 9080 || port == 9443 || port == 8081 || port == 8090;
    }
    
    // 验证HTTP服务
    private static boolean verifyHttpService(Socket socket, String host, int port) {
        try {
            // 判断是HTTP还是HTTPS
            boolean isHttps = (port == 443 || port == 8443 || port == 9443);
            String protocol = isHttps ? "HTTPS" : "HTTP";
            
            // 发送HTTP请求
            OutputStream out = socket.getOutputStream();
            String request = "HEAD / " + protocol + "/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n";
            out.write(request.getBytes(StandardCharsets.UTF_8));
            out.flush();
            
            // 读取响应
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int bytesRead = in.read(buffer);
            
            // 检查响应是否有效
            if (bytesRead > 0) {
                String response = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                // 检查是否包含HTTP状态行
                return response.startsWith("HTTP/") || response.contains("200 OK");
            }
            
            return false;
        } catch (Exception e) {
            log.debug("HTTP服务验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    // 验证MySQL服务
    private static boolean verifyMySQLService(Socket socket) {
        try {
            // 读取MySQL握手包
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int bytesRead = in.read(buffer);
            
            // MySQL服务器会在连接后立即发送握手包
            if (bytesRead > 0) {
                // 检查响应是否包含MySQL特征
                String response = new String(buffer, 0, bytesRead, StandardCharsets.ISO_8859_1);
                return response.contains("mysql") || response.contains("MariaDB");
            }
            
            return false;
        } catch (Exception e) {
            log.debug("MySQL服务验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    // 验证Redis服务
    private static boolean verifyRedisService(Socket socket) {
        try {
            // 发送PING命令
            OutputStream out = socket.getOutputStream();
            out.write("*1\r\n$4\r\nPING\r\n".getBytes(StandardCharsets.UTF_8));
            out.flush();
            
            // 读取响应
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int bytesRead = in.read(buffer);
            
            // Redis应该响应"+PONG"
            if (bytesRead > 0) {
                String response = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                return response.contains("+PONG") || response.contains("-NOAUTH");
            }
            
            return false;
        } catch (Exception e) {
            log.debug("Redis服务验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    // 验证MongoDB服务
    private static boolean verifyMongoDBService(Socket socket) {
        try {
            // MongoDB握手包
            OutputStream out = socket.getOutputStream();
            // 发送一个简单的OP_QUERY命令
            byte[] message = new byte[] {
                0x3F, 0x00, 0x00, 0x00, // 消息长度 (63 bytes)
                0x00, 0x00, 0x00, 0x00, // 请求ID
                0x00, 0x00, 0x00, 0x00, // 响应ID
                (byte)0xD4, 0x07, 0x00, 0x00, // OP_QUERY
                0x00, 0x00, 0x00, 0x00, // 标志
                0x61, 0x64, 0x6D, 0x69, 0x6E, 0x2E, 0x24, 0x63, 0x6D, 0x64, 0x00, // 集合名: "admin.$cmd"
                0x00, 0x00, 0x00, 0x00, // 跳过数量
                0x01, 0x00, 0x00, 0x00, // 返回数量
                0x18, 0x00, 0x00, 0x00, 0x10, 0x69, 0x73, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 // BSON文档: {"ismaster": 1}
            };
            
            out.write(message);
            out.flush();
            
            // 读取响应
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int bytesRead = in.read(buffer);
            
            // 只要有响应就认为是MongoDB服务
            return bytesRead > 0;
        } catch (Exception e) {
            log.debug("MongoDB服务验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    // 为了向后兼容，保留原方法
    private static boolean isPortInUse(int port) {
        return isPortInUse("localhost", port);
    }

    /**
     * 获取监控状态的中文描述
     */
    private String getStatusText(MonitoringStatus status) {
        switch (status) {
            case NORMAL:
                return "正常";
            case WARNING:
                return "警告";
            case ERROR:
                return "错误";
            case UNKNOWN:
            default:
                return "未知";
        }
    }
    
    /**
     * 生成MinIO信息的HTML
     */
    private String generateMinIOInfoHtml(Map<String, Object> metrics) {
        StringBuilder html = new StringBuilder();
        
        // 使用选项卡结构组织MinIO信息
        html.append("<div class=\"minio-tabs\">")
            .append("<div class=\"minio-tab-nav\">")
            .append("<div class=\"minio-tab-item active\">基本信息</div>")
            .append("<div class=\"minio-tab-item\">存储概览</div>")
            .append("<div class=\"minio-tab-item\">性能指标</div>")
            .append("<div class=\"minio-tab-item\">存储桶详情</div>")
            .append("<div class=\"minio-tab-item\">健康检查</div>")
            .append("</div>");

        // 基本信息标签页内容 - 第一个标签
        html.append("<div class=\"minio-tab-content\" style=\"display: block;\">")
            .append("<div class=\"row\">")
            .append("<div class=\"col-12\">")
            .append("<h4>MinIO基本信息</h4>")
            .append("<div class=\"system-info\">");
        
        // MinIO服务端点
        if (metrics.get("endpoint") != null) {
            html.append("<div class=\"system-info-item\">")
                .append("<div class=\"system-info-label\">服务端点:</div>")
                .append("<div class=\"system-info-value\">").append(metrics.get("endpoint")).append("</div>")
                .append("</div>");
        }
        
        // 访问密钥
        if (metrics.get("accessKey") != null) {
            html.append("<div class=\"system-info-item\">")
                .append("<div class=\"system-info-label\">访问密钥:</div>")
                .append("<div class=\"system-info-value\">").append(metrics.get("accessKey")).append("</div>")
                .append("</div>");
        }
        
        // 响应时间
        if (metrics.get("responseTime") != null) {
            html.append("<div class=\"system-info-item\">")
                .append("<div class=\"system-info-label\">响应时间:</div>")
                .append("<div class=\"system-info-value\">").append(metrics.get("responseTime")).append("ms</div>")
                .append("</div>");
        }
        
        // 测试桶状态
        if (metrics.get("testBucketExists") != null) {
            String testBucketStatus = Boolean.TRUE.equals(metrics.get("testBucketExists")) ? "存在" : "不存在";
            html.append("<div class=\"system-info-item\">")
                .append("<div class=\"system-info-label\">测试桶状态:</div>")
                .append("<div class=\"system-info-value\">").append(testBucketStatus).append("</div>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>")
            .append("</div>")
            .append("</div>");
        
        // 存储概览标签页内容 - 第二个标签
        html.append("<div class=\"minio-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">")
            .append("<div class=\"col-12\">")
            .append("<h4>存储概览</h4>")
            .append("<div class=\"thread-stats\">");
        
        // 存储桶总数
        Object bucketsObj = metrics.get("buckets");
        if (bucketsObj instanceof List) {
            List<?> buckets = (List<?>) bucketsObj;
            html.append("<div class=\"stat-card\">")
                .append("<div class=\"stat-value\">").append(buckets.size()).append("</div>")
                .append("<div class=\"stat-label\">存储桶总数</div>")
                .append("</div>");
        }
        
        // 对象总数
        if (metrics.get("totalObjects") != null) {
            html.append("<div class=\"stat-card\">")
                .append("<div class=\"stat-value\">").append(metrics.get("totalObjects")).append("</div>")
                .append("<div class=\"stat-label\">对象总数</div>")
                .append("</div>");
        }
        
        // 总存储容量
        if (metrics.get("totalSize") != null) {
            html.append("<div class=\"stat-card\">")
                .append("<div class=\"stat-value\">").append(metrics.get("totalSize")).append("</div>")
                .append("<div class=\"stat-label\">总存储容量</div>")
                .append("</div>");
        }
        
        html.append("</div>")
            .append("</div>")
            .append("</div>")
            .append("</div>");
        
        // 性能指标标签页内容 - 第三个标签
        html.append("<div class=\"minio-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">")
            .append("<div class=\"col-12\">")
            .append("<h4>性能指标</h4>")
            .append("<div class=\"thread-stats\">");
        
        // 请求成功率
        if (metrics.get("successRate") != null) {
            html.append("<div class=\"stat-card\">")
                .append("<div class=\"stat-value\">").append(metrics.get("successRate")).append("</div>")
                .append("<div class=\"stat-label\">请求成功率</div>")
                .append("</div>");
        }
        
        // 上传速度
        if (metrics.get("uploadSpeed") != null) {
            html.append("<div class=\"stat-card\">")
                .append("<div class=\"stat-value\">").append(metrics.get("uploadSpeed")).append("</div>")
                .append("<div class=\"stat-label\">上传速度</div>")
                .append("</div>");
        }
        
        // 下载速度
        if (metrics.get("downloadSpeed") != null) {
            html.append("<div class=\"stat-card\">")
                .append("<div class=\"stat-value\">").append(metrics.get("downloadSpeed")).append("</div>")
                .append("<div class=\"stat-label\">下载速度</div>")
                .append("</div>");
        }
        
        html.append("</div>");
        
        // API调用统计部分
        if (metrics.get("getRequests") != null || metrics.get("putRequests") != null || metrics.get("deleteRequests") != null) {
            html.append("<h4 style=\"margin-top: 20px;\">API调用统计</h4>")
                .append("<div class=\"thread-stats\">");
            
            // GET请求
            if (metrics.get("getRequests") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(metrics.get("getRequests")).append("</div>")
                    .append("<div class=\"stat-label\">GET请求</div>")
                    .append("</div>");
            }
            
            // PUT请求
            if (metrics.get("putRequests") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(metrics.get("putRequests")).append("</div>")
                    .append("<div class=\"stat-label\">PUT请求</div>")
                    .append("</div>");
            }
            
            // DELETE请求
            if (metrics.get("deleteRequests") != null) {
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(metrics.get("deleteRequests")).append("</div>")
                    .append("<div class=\"stat-label\">DELETE请求</div>")
                    .append("</div>");
            }
            
            html.append("</div>");
        }
        
        html.append("</div>")
            .append("</div>")
            .append("</div>");
        
        // 存储桶详情标签页内容 - 第四个标签
        html.append("<div class=\"minio-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">")
            .append("<div class=\"col-12\">");
        
        // 存储桶详细信息表格
        if (bucketsObj instanceof List) {
            List<?> buckets = (List<?>) bucketsObj;
            if (!buckets.isEmpty()) {
                html.append("<h4>存储桶详细信息</h4>")
                    .append("<table class=\"metrics-table\">")
                    .append("<thead>")
                    .append("<tr>")
                    .append("<th>存储桶名称</th>")
                    .append("<th>创建时间</th>")
                    .append("<th>存储大小</th>")
                    .append("<th>对象数量</th>")
                    .append("<th>访问状态</th>")
                    .append("<th>权限设置</th>")
                    .append("</tr>")
                    .append("</thead>")
                    .append("<tbody>");
                
                for (Object bucketObj : buckets) {
                    if (bucketObj instanceof Map) {
                        Map<?, ?> bucket = (Map<?, ?>) bucketObj;
                        html.append("<tr>");
                        
                        // 存储桶名称
                        html.append("<td>");
                        if (bucket.get("name") != null) {
                            html.append("<span class=\"tag tag-primary\">").append(bucket.get("name")).append("</span>");
                        }
                        html.append("</td>");
                        
                        // 创建时间
                        Object creationDate = bucket.get("creationDate");
                        html.append("<td>").append(creationDate != null ? creationDate : "未知").append("</td>");
                        
                        // 存储大小
                        Object size = bucket.get("size");
                        html.append("<td>").append(size != null ? size : "未知").append("</td>");
                        
                        // 对象数量
                        Object objectCount = bucket.get("objectCount");
                        html.append("<td>").append(objectCount != null ? objectCount : "0").append("</td>");
                        
                        // 访问状态
                        html.append("<td>");
                        Boolean accessible = (Boolean) bucket.get("accessible");
                        if (accessible != null) {
                            String statusTag = accessible ? "success" : "danger";
                            String statusText = accessible ? "可访问" : "不可访问";
                            html.append("<span class=\"tag tag-").append(statusTag).append("\">").append(statusText).append("</span>");
                        } else {
                            html.append("未知");
                        }
                        html.append("</td>");
                        
                        // 权限设置
                        html.append("<td>");
                        Object policyObj = bucket.get("policy");
                        String policy = policyObj != null ? policyObj.toString() : "private";
                        String policyTag = "public".equals(policy) ? "warning" : "info";
                        String policyText = "public".equals(policy) ? "公共" : "私有";
                        html.append("<span class=\"tag tag-").append(policyTag).append("\">").append(policyText).append("</span>");
                        html.append("</td>");
                        
                        html.append("</tr>");
                    }
                }
                
                html.append("</tbody>")
                    .append("</table>");
            } else {
                html.append("<p>暂无存储桶数据</p>");
            }
        } else {
            html.append("<p>暂无存储桶数据</p>");
        }
        
        html.append("</div>")
            .append("</div>")
            .append("</div>");
        
        // 健康检查标签页内容 - 第五个标签
        html.append("<div class=\"minio-tab-content\" style=\"display: none;\">")
            .append("<div class=\"row\">")
            .append("<div class=\"col-12\">")
            .append("<h4>健康检查</h4>");
        
        // 健康检查
        if (metrics.get("connectionHealthy") != null || metrics.get("bucketsAccessible") != null || 
            metrics.get("authenticationSuccessful") != null) {
            html.append("<div class=\"thread-stats\">");
            
            // 连接测试
            if (metrics.get("connectionHealthy") != null) {
                Boolean healthy = (Boolean) metrics.get("connectionHealthy");
                String healthyTag = healthy ? "success" : "danger";
                String healthyText = healthy ? "通过" : "失败";
                String healthyIcon = healthy ? "✓" : "✗";
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(healthyIcon).append("</div>")
                    .append("<div class=\"stat-label\">连接测试</div>")
                    .append("<div><span class=\"tag tag-").append(healthyTag).append("\">").append(healthyText).append("</span></div>")
                    .append("</div>");
            }
            
            // 存储桶访问
            if (metrics.get("bucketsAccessible") != null) {
                Boolean accessible = (Boolean) metrics.get("bucketsAccessible");
                String accessibleTag = accessible ? "success" : "warning";
                String accessibleText = accessible ? "正常" : "异常";
                String accessibleIcon = accessible ? "✓" : "⚠";
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(accessibleIcon).append("</div>")
                    .append("<div class=\"stat-label\">存储桶访问</div>")
                    .append("<div><span class=\"tag tag-").append(accessibleTag).append("\">").append(accessibleText).append("</span></div>")
                    .append("</div>");
            }
            
            // 认证状态
            if (metrics.get("authenticationSuccessful") != null) {
                Boolean authSuccess = (Boolean) metrics.get("authenticationSuccessful");
                String authTag = authSuccess ? "success" : "danger";
                String authText = authSuccess ? "认证成功" : "认证失败";
                String authIcon = authSuccess ? "✓" : "✗";
                html.append("<div class=\"stat-card\">")
                    .append("<div class=\"stat-value\">").append(authIcon).append("</div>")
                    .append("<div class=\"stat-label\">认证状态</div>")
                    .append("<div><span class=\"tag tag-").append(authTag).append("\">").append(authText).append("</span></div>")
                    .append("</div>");
            }
            
            html.append("</div>");
        } else {
            html.append("<p>暂无健康检查数据</p>");
        }
        
        html.append("</div>")
            .append("</div>")
            .append("</div>");
        
        html.append("</div>");
        
        return html.toString();
    }

    @Override
    public MonitoringResult monitorSystem() {
        // 先检查缓存
        MonitoringResult cachedResult = getCachedResult("System");
        if (cachedResult != null) {
            log.debug("返回系统资源监控缓存结果");
            return cachedResult;
        }
        log.info("开始监控系统资源");
        
        try {
            Map<String, Object> systemMetrics = new HashMap<>();
            
            // 获取系统基本信息
            Map<String, Object> basicInfo = getSystemBasicInfo();
            systemMetrics.put("basic", basicInfo);
            log.debug("系统基本信息: {}", basicInfo);
            
            // 获取磁盘信息
            Map<String, Object> diskInfo = getDiskInfo();
            systemMetrics.put("disk", diskInfo);
            log.debug("磁盘信息: {}", diskInfo);
            
            // 获取内存信息
            Map<String, Object> memoryInfo = getMemoryInfo();
            systemMetrics.put("memory", memoryInfo);
            log.debug("内存信息: {}", memoryInfo);
            
            // 获取进程信息
            Map<String, Object> processInfo = getProcessInfo();
            systemMetrics.put("process", processInfo);
            log.debug("进程信息: {}", processInfo);
            
            // 获取端口信息
            Map<String, Object> portInfo = getPortInfo();
            systemMetrics.put("ports", portInfo);
            log.debug("端口信息: {}", portInfo);
            
            // 获取CPU信息
            Map<String, Object> cpuInfo = getCpuInfo();
            systemMetrics.put("cpu", cpuInfo);
            log.debug("CPU信息: {}", cpuInfo);
            
            MonitoringResult result = MonitoringResult.builder()
                    .name("System")
                    .status(MonitoringStatus.NORMAL)
                    .details("系统资源监控正常")
                    .monitorTime(LocalDateTime.now())
                    .metrics(systemMetrics)
                    .build();
            
            // 存储监控结果
            monitoringResults.put("System", result);
            log.info("系统资源监控完成，结果已保存到monitoringResults");
            log.info("系统监控指标数量: {}", systemMetrics.size());
            putToCache("System", result);
            return result;
            
        } catch (Exception e) {
            log.error("系统资源监控失败", e);
            
            MonitoringResult result = MonitoringResult.builder()
                    .name("System")
                    .status(MonitoringStatus.ERROR)
                    .details("系统资源监控失败: " + e.getMessage())
                    .monitorTime(LocalDateTime.now())
                    .metrics(new HashMap<>())
                    .build();
            
            monitoringResults.put("System", result);
            return result;
        }
    }
    
    /**
     * 获取系统基本信息
     */
    private Map<String, Object> getSystemBasicInfo() {
        Map<String, Object> basicInfo = new HashMap<>();
        
        try {
            // 操作系统信息
            basicInfo.put("osName", System.getProperty("os.name"));
            basicInfo.put("osVersion", System.getProperty("os.version"));
            basicInfo.put("osArch", System.getProperty("os.arch"));
            
            // Java信息
            basicInfo.put("javaVersion", System.getProperty("java.version"));
            basicInfo.put("javaVendor", System.getProperty("java.vendor"));
            
            // 系统启动时间
            RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
            long startTime = runtimeBean.getStartTime();
            basicInfo.put("systemStartTime", formatTime(LocalDateTime.ofInstant(
                Instant.ofEpochMilli(startTime), ZoneId.systemDefault())));
            
            // 运行时长
            long uptime = runtimeBean.getUptime();
            basicInfo.put("uptime", formatUptime(uptime));
            
            // 用户信息
            basicInfo.put("userName", System.getProperty("user.name"));
            basicInfo.put("userHome", System.getProperty("user.home"));
            basicInfo.put("workingDirectory", System.getProperty("user.dir"));
            
        } catch (Exception e) {
            log.error("获取系统基本信息失败", e);
            basicInfo.put("error", "获取系统基本信息失败: " + e.getMessage());
        }
        
        return basicInfo;
    }
    
    /**
     * 获取磁盘信息
     */
    private Map<String, Object> getDiskInfo() {
        Map<String, Object> diskInfo = new HashMap<>();
        List<Map<String, Object>> diskList = new ArrayList<>();
        
        try {
            File[] roots = File.listRoots();
            long totalSpace = 0;
            long usableSpace = 0;
            long usedSpace = 0;
            
            for (File root : roots) {
                Map<String, Object> diskDetail = new HashMap<>();
                
                long total = root.getTotalSpace();
                long usable = root.getUsableSpace();
                long used = total - usable;
                
                totalSpace += total;
                usableSpace += usable;
                usedSpace += used;
                
                diskDetail.put("path", root.getAbsolutePath());
                diskDetail.put("totalSpace", formatByteSize(String.valueOf(total)));
                diskDetail.put("usableSpace", formatByteSize(String.valueOf(usable)));
                diskDetail.put("usedSpace", formatByteSize(String.valueOf(used)));
                
                if (total > 0) {
                    double usagePercent = (double) used / total * 100;
                    diskDetail.put("usagePercent", String.format("%.2f%%", usagePercent));
                } else {
                    diskDetail.put("usagePercent", "0.00%");
                }
                
                diskList.add(diskDetail);
            }
            
            // 总计信息
            diskInfo.put("totalSpace", formatByteSize(String.valueOf(totalSpace)));
            diskInfo.put("usableSpace", formatByteSize(String.valueOf(usableSpace)));
            diskInfo.put("usedSpace", formatByteSize(String.valueOf(usedSpace)));
            
            if (totalSpace > 0) {
                double totalUsagePercent = (double) usedSpace / totalSpace * 100;
                diskInfo.put("totalUsagePercent", String.format("%.2f%%", totalUsagePercent));
            } else {
                diskInfo.put("totalUsagePercent", "0.00%");
            }
            
            diskInfo.put("disks", diskList);
            
        } catch (Exception e) {
            log.error("获取磁盘信息失败", e);
            diskInfo.put("error", "获取磁盘信息失败: " + e.getMessage());
        }
        
        return diskInfo;
    }
    
    /**
     * 获取内存信息
     */
    private Map<String, Object> getMemoryInfo() {
        Map<String, Object> memoryInfo = new HashMap<>();
        
        try {
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            
            // JVM内存信息
            MemoryUsage heapMemory = memoryBean.getHeapMemoryUsage();
            MemoryUsage nonHeapMemory = memoryBean.getNonHeapMemoryUsage();
            
            Map<String, Object> jvmMemory = new HashMap<>();
            jvmMemory.put("heapUsed", formatByteSize(String.valueOf(heapMemory.getUsed())));
            jvmMemory.put("heapMax", formatByteSize(String.valueOf(heapMemory.getMax())));
            jvmMemory.put("nonHeapUsed", formatByteSize(String.valueOf(nonHeapMemory.getUsed())));
            jvmMemory.put("nonHeapMax", formatByteSize(String.valueOf(nonHeapMemory.getMax())));
            
            memoryInfo.put("jvm", jvmMemory);
            
            // 系统内存信息（如果可用）
            if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
                com.sun.management.OperatingSystemMXBean sunOsBean = 
                    (com.sun.management.OperatingSystemMXBean) osBean;
                
                Map<String, Object> systemMemory = new HashMap<>();
                long totalPhysical = sunOsBean.getTotalPhysicalMemorySize();
                long freePhysical = sunOsBean.getFreePhysicalMemorySize();
                long usedPhysical = totalPhysical - freePhysical;
                
                systemMemory.put("totalPhysical", formatByteSize(String.valueOf(totalPhysical)));
                systemMemory.put("freePhysical", formatByteSize(String.valueOf(freePhysical)));
                systemMemory.put("usedPhysical", formatByteSize(String.valueOf(usedPhysical)));
                
                if (totalPhysical > 0) {
                    double usagePercent = (double) usedPhysical / totalPhysical * 100;
                    systemMemory.put("physicalUsagePercent", String.format("%.2f%%", usagePercent));
                }
                
                // 交换空间信息
                long totalSwap = sunOsBean.getTotalSwapSpaceSize();
                long freeSwap = sunOsBean.getFreeSwapSpaceSize();
                long usedSwap = totalSwap - freeSwap;
                
                systemMemory.put("totalSwap", formatByteSize(String.valueOf(totalSwap)));
                systemMemory.put("freeSwap", formatByteSize(String.valueOf(freeSwap)));
                systemMemory.put("usedSwap", formatByteSize(String.valueOf(usedSwap)));
                
                if (totalSwap > 0) {
                    double swapUsagePercent = (double) usedSwap / totalSwap * 100;
                    systemMemory.put("swapUsagePercent", String.format("%.2f%%", swapUsagePercent));
                }
                
                memoryInfo.put("system", systemMemory);
            }
            
        } catch (Exception e) {
            log.error("获取内存信息失败", e);
            memoryInfo.put("error", "获取内存信息失败: " + e.getMessage());
        }
        
        return memoryInfo;
    }
    
    /**
     * 获取进程信息
     */
    private Map<String, Object> getProcessInfo() {
        Map<String, Object> processInfo = new HashMap<>();
        
        try {
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            
            // CPU核心数
            int availableProcessors = osBean.getAvailableProcessors();
            processInfo.put("cpuCores", availableProcessors);
            
            // 系统负载
            double systemLoadAverage = osBean.getSystemLoadAverage();
            if (systemLoadAverage >= 0) {
                processInfo.put("systemLoadAverage", String.format("%.2f", systemLoadAverage));
            } else {
                processInfo.put("systemLoadAverage", "不支持");
            }
            
            // 获取进程数（通过系统命令）
            String osName = System.getProperty("os.name").toLowerCase();
            if (osName.contains("windows")) {
                processInfo.putAll(getWindowsProcessInfo());
            } else {
                processInfo.putAll(getLinuxProcessInfo());
            }
            
        } catch (Exception e) {
            log.error("获取进程信息失败", e);
            processInfo.put("error", "获取进程信息失败: " + e.getMessage());
        }
        
        return processInfo;
    }
    
    /**
     * 获取Windows进程信息
     */
    private Map<String, Object> getWindowsProcessInfo() {
        Map<String, Object> processInfo = new HashMap<>();
        
        try {
            // 获取进程数
            ProcessBuilder pb = new ProcessBuilder("tasklist", "/fo", "csv");
            Process process = pb.start();
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), "GBK"))) {
                
                long processCount = reader.lines().skip(1).count(); // 跳过标题行
                processInfo.put("processCount", processCount);
            }
            
            process.waitFor();
            
        } catch (Exception e) {
            log.error("获取Windows进程信息失败", e);
            processInfo.put("processCount", "获取失败");
        }
        
        return processInfo;
    }
    
    /**
     * 获取Linux进程信息
     */
    private Map<String, Object> getLinuxProcessInfo() {
        Map<String, Object> processInfo = new HashMap<>();
        
        try {
            // 获取进程数
            ProcessBuilder pb = new ProcessBuilder("ps", "aux");
            Process process = pb.start();
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                
                long processCount = reader.lines().skip(1).count(); // 跳过标题行
                processInfo.put("processCount", processCount);
            }
            
            process.waitFor();
            
        } catch (Exception e) {
            log.error("获取Linux进程信息失败", e);
            processInfo.put("processCount", "获取失败");
        }
        
        return processInfo;
    }
    
    /**
     * 获取端口信息
     */
    private Map<String, Object> getPortInfo() {
        Map<String, Object> portInfo = new HashMap<>();
        
        try {
            String osName = System.getProperty("os.name").toLowerCase();
            
            if (osName.contains("windows")) {
                portInfo.putAll(getWindowsPortInfo());
            } else {
                portInfo.putAll(getUnixPortInfo());
            }
            
        } catch (Exception e) {
            log.error("获取端口信息失败", e);
            portInfo.put("error", "获取端口信息失败: " + e.getMessage());
        }
        
        return portInfo;
    }
    
    /**
     * 获取Windows端口信息
     */
    private Map<String, Object> getWindowsPortInfo() {
        Map<String, Object> portInfo = new HashMap<>();
        List<Map<String, String>> listeningPorts = new ArrayList<>();
        
        try {
            ProcessBuilder pb = new ProcessBuilder("netstat", "-an");
            Process process = pb.start();
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), "GBK"))) {
                
                String line;
                int tcpCount = 0;
                int udpCount = 0;
                int listeningCount = 0;
                
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    if (line.startsWith("TCP")) {
                        tcpCount++;
                        if (line.contains("LISTENING")) {
                            listeningCount++;
                            String[] parts = line.split("\\s+");
                            if (parts.length >= 2) {
                                Map<String, String> portDetail = new HashMap<>();
                                portDetail.put("protocol", "TCP");
                                portDetail.put("address", parts[1]);
                                portDetail.put("state", "LISTENING");
                                listeningPorts.add(portDetail);
                            }
                        }
                    } else if (line.startsWith("UDP")) {
                        udpCount++;
                    }
                }
                
                portInfo.put("tcpConnections", tcpCount);
                portInfo.put("udpConnections", udpCount);
                portInfo.put("listeningPorts", listeningCount);
                portInfo.put("portDetails", listeningPorts.subList(0, Math.min(20, listeningPorts.size()))); // 限制显示前20个
            }
            
            process.waitFor();
            
        } catch (Exception e) {
            log.error("获取Windows端口信息失败", e);
            portInfo.put("error", "获取Windows端口信息失败: " + e.getMessage());
        }
        
        return portInfo;
    }
    
    /**
     * 获取Unix系统（Linux/macOS）端口信息
     */
    private Map<String, Object> getUnixPortInfo() {
        Map<String, Object> portInfo = new HashMap<>();
        List<Map<String, String>> listeningPorts = new ArrayList<>();
        
        try {
            // 尝试使用netstat命令，兼容Linux和macOS
            ProcessBuilder pb;
            String osName = System.getProperty("os.name").toLowerCase();
            
            if (osName.contains("mac")) {
                // macOS系统使用不同的netstat参数
                pb = new ProcessBuilder("netstat", "-an", "-p", "tcp");
            } else {
                // Linux系统使用标准参数
                pb = new ProcessBuilder("netstat", "-tuln");
            }
            
            Process process = pb.start();
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                
                String line;
                int tcpCount = 0;
                int udpCount = 0;
                int listeningCount = 0;
                
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    
                    if (osName.contains("mac")) {
                        // macOS的netstat输出格式处理
                        if (line.startsWith("tcp") || line.startsWith("tcp4") || line.startsWith("tcp6")) {
                            tcpCount++;
                            if (line.contains("LISTEN")) {
                                listeningCount++;
                                String[] parts = line.split("\\s+");
                                if (parts.length >= 4) {
                                    Map<String, String> portDetail = new HashMap<>();
                                    portDetail.put("protocol", parts[0].toUpperCase());
                                    portDetail.put("address", parts[3]);
                                    portDetail.put("state", "LISTEN");
                                    listeningPorts.add(portDetail);
                                }
                            }
                        } else if (line.startsWith("udp") || line.startsWith("udp4") || line.startsWith("udp6")) {
                            udpCount++;
                        }
                    } else {
                        // Linux的netstat输出格式处理
                        if (line.startsWith("tcp")) {
                            tcpCount++;
                            if (line.contains("LISTEN")) {
                                listeningCount++;
                                String[] parts = line.split("\\s+");
                                if (parts.length >= 4) {
                                    Map<String, String> portDetail = new HashMap<>();
                                    portDetail.put("protocol", "TCP");
                                    portDetail.put("address", parts[3]);
                                    portDetail.put("state", "LISTEN");
                                    listeningPorts.add(portDetail);
                                }
                            }
                        } else if (line.startsWith("udp")) {
                            udpCount++;
                        }
                    }
                }
                
                portInfo.put("tcpConnections", tcpCount);
                portInfo.put("udpConnections", udpCount);
                portInfo.put("listeningPorts", listeningCount);
                portInfo.put("portDetails", listeningPorts.subList(0, Math.min(20, listeningPorts.size()))); // 限制显示前20个
            }
            
            process.waitFor();
            
        } catch (Exception e) {
            log.error("获取Unix系统端口信息失败", e);
            
            // 如果netstat命令失败，尝试使用备用方法
            try {
                return getUnixPortInfoFallback();
            } catch (Exception fallbackException) {
                log.error("备用方法也失败", fallbackException);
                portInfo.put("error", "获取端口信息失败: " + e.getMessage());
            }
        }
        
        return portInfo;
    }
    
    /**
     * Unix系统端口信息获取的备用方法
     */
    private Map<String, Object> getUnixPortInfoFallback() {
        Map<String, Object> portInfo = new HashMap<>();
        List<Map<String, String>> listeningPorts = new ArrayList<>();
        
        try {
            String osName = System.getProperty("os.name").toLowerCase();
            ProcessBuilder pb;
            
            if (osName.contains("mac")) {
                // macOS备用命令：使用lsof
                pb = new ProcessBuilder("lsof", "-i", "-P", "-n");
            } else {
                // Linux备用命令：使用ss
                pb = new ProcessBuilder("ss", "-tuln");
            }
            
            Process process = pb.start();
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                
                String line;
                int tcpCount = 0;
                int udpCount = 0;
                int listeningCount = 0;
                
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    
                    if (osName.contains("mac")) {
                        // 处理lsof输出
                        if (line.contains("TCP") && line.contains("LISTEN")) {
                            tcpCount++;
                            listeningCount++;
                            String[] parts = line.split("\\s+");
                            if (parts.length >= 9) {
                                Map<String, String> portDetail = new HashMap<>();
                                portDetail.put("protocol", "TCP");
                                portDetail.put("address", parts[8]);
                                portDetail.put("state", "LISTEN");
                                listeningPorts.add(portDetail);
                            }
                        } else if (line.contains("UDP")) {
                            udpCount++;
                        }
                    } else {
                        // 处理ss输出
                        if (line.startsWith("tcp")) {
                            tcpCount++;
                            if (line.contains("LISTEN")) {
                                listeningCount++;
                                String[] parts = line.split("\\s+");
                                if (parts.length >= 5) {
                                    Map<String, String> portDetail = new HashMap<>();
                                    portDetail.put("protocol", "TCP");
                                    portDetail.put("address", parts[4]);
                                    portDetail.put("state", "LISTEN");
                                    listeningPorts.add(portDetail);
                                }
                            }
                        } else if (line.startsWith("udp")) {
                            udpCount++;
                        }
                    }
                }
                
                portInfo.put("tcpConnections", tcpCount);
                portInfo.put("udpConnections", udpCount);
                portInfo.put("listeningPorts", listeningCount);
                portInfo.put("portDetails", listeningPorts.subList(0, Math.min(20, listeningPorts.size())));
            }
            
            process.waitFor();
            
        } catch (Exception e) {
            log.error("备用方法获取端口信息失败", e);
            portInfo.put("error", "获取端口信息失败: " + e.getMessage());
        }
        
        return portInfo;
    }
    
    /**
     * 获取CPU信息
     */
    private Map<String, Object> getCpuInfo() {
        Map<String, Object> cpuInfo = new HashMap<>();
        
        try {
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            
            // CPU核心数
            cpuInfo.put("availableProcessors", osBean.getAvailableProcessors());
            
            // 系统负载
            double loadAverage = osBean.getSystemLoadAverage();
            if (loadAverage >= 0) {
                cpuInfo.put("systemLoadAverage", String.format("%.2f", loadAverage));
                
                // 计算负载百分比
                double loadPercent = (loadAverage / osBean.getAvailableProcessors()) * 100;
                cpuInfo.put("loadPercent", String.format("%.2f%%", Math.min(100, loadPercent)));
            } else {
                cpuInfo.put("systemLoadAverage", "不支持");
                cpuInfo.put("loadPercent", "不支持");
            }
            
            // CPU使用率（如果可用）
            if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
                com.sun.management.OperatingSystemMXBean sunOsBean = 
                    (com.sun.management.OperatingSystemMXBean) osBean;
                
                double processCpuLoad = sunOsBean.getProcessCpuLoad();
                double systemCpuLoad = sunOsBean.getSystemCpuLoad();
                
                if (processCpuLoad >= 0) {
                    cpuInfo.put("processCpuUsage", String.format("%.2f%%", processCpuLoad * 100));
                }
                
                if (systemCpuLoad >= 0) {
                    cpuInfo.put("systemCpuUsage", String.format("%.2f%%", systemCpuLoad * 100));
                }
            }
            
        } catch (Exception e) {
            log.error("获取CPU信息失败", e);
            cpuInfo.put("error", "获取CPU信息失败: " + e.getMessage());
        }
        
        return cpuInfo;
    }

    /**
     * 生成系统资源监控HTML
     */
    private String generateSystemMonitoringHtml(MonitoringResult systemResult) {
        StringBuilder html = new StringBuilder();
        
        // 获取状态的中文描述
        String statusText = getStatusText(systemResult.getStatus());
        
        // 添加状态信息
        html.append("<div class=\"row\">")
            .append("<div class=\"col-12\">")
            .append("<div class=\"tag tag-").append(systemResult.getStatus()).append("\">")
            .append(statusText).append("</div>")
            .append("<p>").append(systemResult.getDetails()).append("</p>")
            .append("<p>最后监控时间: ").append(formatTime(systemResult.getMonitorTime())).append("</p>")
            .append("</div>")
            .append("</div>");
        
        // 只有在有指标数据时才添加选项卡
        if (systemResult.getMetrics() != null && !systemResult.getMetrics().isEmpty()) {
            html.append("<div class=\"system-tabs\">")
                .append("<div class=\"system-tab-nav\">")
                .append("<div class=\"system-tab-item active\">基本信息</div>")
                .append("<div class=\"system-tab-item\">磁盘信息</div>")
                .append("<div class=\"system-tab-item\">内存信息</div>")
                .append("<div class=\"system-tab-item\">CPU和进程</div>")
                .append("<div class=\"system-tab-item\">端口信息</div>")
                .append("</div>");

            // 基本信息标签页内容
            html.append("<div class=\"system-tab-content\" style=\"display: block;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> basicInfo = (Map<String, Object>) systemResult.getMetrics().get("basic");
            if (basicInfo != null && !basicInfo.isEmpty()) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>系统基本信息</h4>")
                    .append("<div class=\"overview-stats\">");
                
                if (basicInfo.get("osName") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(basicInfo.get("osName")).append("</div>")
                        .append("<div class=\"stat-label\">操作系统</div>")
                        .append("</div>");
                }
                
                if (basicInfo.get("javaVersion") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(basicInfo.get("javaVersion")).append("</div>")
                        .append("<div class=\"stat-label\">Java版本</div>")
                        .append("</div>");
                }
                
                if (basicInfo.get("osArch") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(basicInfo.get("osArch")).append("</div>")
                        .append("<div class=\"stat-label\">系统架构</div>")
                        .append("</div>");
                }
                
                if (basicInfo.get("userName") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(basicInfo.get("userName")).append("</div>")
                        .append("<div class=\"stat-label\">用户名</div>")
                        .append("</div>");
                }
                
                html.append("</div>")
                    .append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无系统基本信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            // 磁盘信息标签页
            html.append("<div class=\"system-tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> diskInfo = (Map<String, Object>) systemResult.getMetrics().get("disk");
            if (diskInfo != null && !diskInfo.isEmpty()) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>磁盘使用统计</h4>")
                    .append("<div class=\"overview-stats\">");
                
                if (diskInfo.get("totalSpace") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(diskInfo.get("totalSpace")).append("</div>")
                        .append("<div class=\"stat-label\">总空间</div>")
                        .append("</div>");
                }
                
                if (diskInfo.get("usedSpace") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(diskInfo.get("usedSpace")).append("</div>")
                        .append("<div class=\"stat-label\">已使用</div>")
                        .append("</div>");
                }
                
                if (diskInfo.get("usableSpace") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(diskInfo.get("usableSpace")).append("</div>")
                        .append("<div class=\"stat-label\">可用空间</div>")
                        .append("</div>");
                }
                
                if (diskInfo.get("totalUsagePercent") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(diskInfo.get("totalUsagePercent")).append("</div>")
                        .append("<div class=\"stat-label\">使用率</div>")
                        .append("</div>");
                }
                
                html.append("</div>");
                
                // 磁盘分区详情表格
                List<Map<String, Object>> disks = (List<Map<String, Object>>) diskInfo.get("disks");
                if (disks != null && !disks.isEmpty()) {
                    html.append("<h4>磁盘分区详情</h4>")
                        .append("<table class=\"table\">")
                        .append("<thead>")
                        .append("<tr>")
                        .append("<th>分区</th>")
                        .append("<th>总空间</th>")
                        .append("<th>已使用</th>")
                        .append("<th>可用空间</th>")
                        .append("<th>使用率</th>")
                        .append("</tr>")
                        .append("</thead>")
                        .append("<tbody>");
                    
                    for (Map<String, Object> disk : disks) {
                        html.append("<tr>")
                            .append("<td>").append(disk.getOrDefault("path", "N/A")).append("</td>")
                            .append("<td>").append(disk.getOrDefault("totalSpace", "N/A")).append("</td>")
                            .append("<td>").append(disk.getOrDefault("usedSpace", "N/A")).append("</td>")
                            .append("<td>").append(disk.getOrDefault("usableSpace", "N/A")).append("</td>")
                            .append("<td>").append(disk.getOrDefault("usagePercent", "N/A")).append("</td>")
                            .append("</tr>");
                    }
                    
                    html.append("</tbody>")
                        .append("</table>");
                }
                
                html.append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无磁盘信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            // 内存信息标签页
            html.append("<div class=\"system-tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> memoryInfo = (Map<String, Object>) systemResult.getMetrics().get("memory");
            if (memoryInfo != null && !memoryInfo.isEmpty()) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>内存使用情况</h4>");
                
                // JVM内存信息
                Map<String, Object> jvmMemory = (Map<String, Object>) memoryInfo.get("jvm");
                if (jvmMemory != null && !jvmMemory.isEmpty()) {
                    html.append("<h5>JVM内存</h5>")
                        .append("<div class=\"overview-stats\">");
                    
                    if (jvmMemory.get("heapUsed") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(jvmMemory.get("heapUsed")).append("</div>")
                            .append("<div class=\"stat-label\">堆内存已使用</div>")
                            .append("</div>");
                    }
                    
                    if (jvmMemory.get("heapMax") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(jvmMemory.get("heapMax")).append("</div>")
                            .append("<div class=\"stat-label\">堆内存最大值</div>")
                            .append("</div>");
                    }
                    
                    html.append("</div>");
                }
                
                // 系统内存信息
                Map<String, Object> systemMemory = (Map<String, Object>) memoryInfo.get("system");
                if (systemMemory != null && !systemMemory.isEmpty()) {
                    html.append("<h5>系统内存</h5>")
                        .append("<div class=\"overview-stats\">");
                    
                    if (systemMemory.get("totalPhysical") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(systemMemory.get("totalPhysical")).append("</div>")
                            .append("<div class=\"stat-label\">物理内存总量</div>")
                            .append("</div>");
                    }
                    
                    if (systemMemory.get("usedPhysical") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(systemMemory.get("usedPhysical")).append("</div>")
                            .append("<div class=\"stat-label\">物理内存已使用</div>")
                            .append("</div>");
                    }
                    
                    if (systemMemory.get("freePhysical") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(systemMemory.get("freePhysical")).append("</div>")
                            .append("<div class=\"stat-label\">物理内存空闲</div>")
                            .append("</div>");
                    }
                    
                    if (systemMemory.get("physicalUsagePercent") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(systemMemory.get("physicalUsagePercent")).append("</div>")
                            .append("<div class=\"stat-label\">物理内存使用率</div>")
                            .append("</div>");
                    }
                    
                    html.append("</div>");
                }
                
                html.append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无内存信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            // CPU和进程信息标签页
            html.append("<div class=\"system-tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> processInfo = (Map<String, Object>) systemResult.getMetrics().get("process");
            Map<String, Object> cpuInfo = (Map<String, Object>) systemResult.getMetrics().get("cpu");
            
            if ((processInfo != null && !processInfo.isEmpty()) || (cpuInfo != null && !cpuInfo.isEmpty())) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>CPU和进程信息</h4>")
                    .append("<div class=\"overview-stats\">");
                
                // CPU信息
                if (cpuInfo != null) {
                    if (cpuInfo.get("availableProcessors") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(cpuInfo.get("availableProcessors")).append("</div>")
                            .append("<div class=\"stat-label\">CPU核心数</div>")
                            .append("</div>");
                    }
                    
                    if (cpuInfo.get("systemLoadAverage") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(cpuInfo.get("systemLoadAverage")).append("</div>")
                            .append("<div class=\"stat-label\">系统负载</div>")
                            .append("</div>");
                    }
                }
                
                // 进程信息
                if (processInfo != null) {
                    if (processInfo.get("cpuCores") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(processInfo.get("cpuCores")).append("</div>")
                            .append("<div class=\"stat-label\">CPU核心数</div>")
                            .append("</div>");
                    }
                    
                    if (processInfo.get("systemLoadAverage") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(processInfo.get("systemLoadAverage")).append("</div>")
                            .append("<div class=\"stat-label\">系统负载</div>")
                            .append("</div>");
                    }
                    
                    if (processInfo.get("processCount") != null) {
                        html.append("<div class=\"stat-card\">")
                            .append("<div class=\"stat-value-sm\">").append(processInfo.get("processCount")).append("</div>")
                            .append("<div class=\"stat-label\">运行进程数</div>")
                            .append("</div>");
                    }
                }
                
                html.append("</div>")
                    .append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无CPU和进程信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            // 端口信息标签页
            html.append("<div class=\"system-tab-content\" style=\"display: none;\">")
                .append("<div class=\"row\">");
            
            Map<String, Object> portInfo = (Map<String, Object>) systemResult.getMetrics().get("ports");
            if (portInfo != null && !portInfo.isEmpty()) {
                html.append("<div class=\"col-12\">")
                    .append("<h4>网络连接统计</h4>")
                    .append("<div class=\"overview-stats\">");
                
                if (portInfo.get("tcpConnections") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(portInfo.get("tcpConnections")).append("</div>")
                        .append("<div class=\"stat-label\">TCP连接数</div>")
                        .append("</div>");
                }
                
                if (portInfo.get("udpConnections") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(portInfo.get("udpConnections")).append("</div>")
                        .append("<div class=\"stat-label\">UDP连接数</div>")
                        .append("</div>");
                }
                
                if (portInfo.get("listeningPorts") != null) {
                    html.append("<div class=\"stat-card\">")
                        .append("<div class=\"stat-value-sm\">").append(portInfo.get("listeningPorts")).append("</div>")
                        .append("<div class=\"stat-label\">监听端口数</div>")
                        .append("</div>");
                }
                
                html.append("</div>");
                
                // 端口详情表格
                List<Map<String, Object>> portDetails = (List<Map<String, Object>>) portInfo.get("portDetails");
                if (portDetails != null && !portDetails.isEmpty()) {
                    html.append("<h4>监听端口详情</h4>")
                        .append("<table class=\"table\">")
                        .append("<thead>")
                        .append("<tr>")
                        .append("<th>协议</th>")
                        // .append("<th>端口</th>")
                        .append("<th>地址</th>")
                        .append("<th>状态</th>")
                        .append("</tr>")
                        .append("</thead>")
                        .append("<tbody>");
                    
                    for (Map<String, Object> detail : portDetails) {
                        html.append("<tr>")
                            .append("<td>").append(detail.getOrDefault("protocol", "N/A")).append("</td>")
                            // .append("<td>").append(detail.getOrDefault("port", "N/A")).append("</td>")
                            .append("<td>").append(detail.getOrDefault("address", "N/A")).append("</td>")
                            .append("<td>").append(detail.getOrDefault("state", "N/A")).append("</td>")
                            .append("</tr>");
                    }
                    
                    html.append("</tbody>")
                        .append("</table>");
                }
                
                html.append("</div>");
            } else {
                html.append("<div class=\"col-12\">")
                    .append("<p>暂无端口信息数据</p>")
                    .append("</div>");
            }
            
            html.append("</div>")
                .append("</div>");
            
            html.append("</div>");
        } else {
            html.append("<div class=\"row\">")
                .append("<div class=\"col-12\">")
                .append("<p>暂无系统监控数据</p>")
                .append("</div>")
                .append("</div>");
        }
        
        return html.toString();
    }

    public static void main(String[] args) throws Exception {
        // 测试系统监控功能
        MonitoringServiceImpl service = new MonitoringServiceImpl(null, null, null, null);
        
        System.out.println("=== 测试系统监控功能 ===");
        
        try {
            MonitoringResult result = service.monitorSystem();
            System.out.println("监控结果名称: " + result.getName());
            System.out.println("监控状态: " + result.getStatus());
            System.out.println("监控详情: " + result.getDetails());
            System.out.println("监控指标数量: " + (result.getMetrics() != null ? result.getMetrics().size() : 0));
            
            if (result.getMetrics() != null) {
                System.out.println("监控指标键: " + result.getMetrics().keySet());
                
                // 检查每个指标的内容
                for (Map.Entry<String, Object> entry : result.getMetrics().entrySet()) {
                    System.out.println("指标 " + entry.getKey() + ": " + 
                        (entry.getValue() instanceof Map ? ((Map<?, ?>) entry.getValue()).keySet() : entry.getValue()));
                }
            }
            
            // 测试HTML生成
            String html = service.generateSystemMonitoringHtml(result);
            System.out.println("生成的HTML长度: " + html.length());
            System.out.println("HTML前100个字符: " + html.substring(0, Math.min(100, html.length())));
            
        } catch (Exception e) {
            System.err.println("测试失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
} 